文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

“覆盖率检测”的实现原理,就这?

2024-12-02 19:50

关注

覆盖率检测是用来判断单测完整性的,jest 和 karma 都提供了这种功能:

 

覆盖率就是执行过的代码占总代码的比例,比如执行了多少行(Line),执行了多少个分支(Branch),执行了多少个函数(Function),执行了多少条语句(Statement)。

用它比上总的数量就是覆盖率,分为行覆盖率、分支覆盖率、函数覆盖率、语句覆盖率等。

看起来是不是很神奇,执行完一遍就能知道覆盖到了哪些代码,其实实现原理比较简单,相信看完这篇文章,你会有“就这?”的感觉。

原理探究

jest 和 karama 都是基于 istanbul 做的覆盖率检测,我们来探究下 istanbul 的实现原理。

测试代码如下: 

我们执行 istanbul 的 instrument 命令:

  1. npx istanbul instrument ./test.js -o ./out.js 

instrument 是指函数插桩,也就是透明的给函数添加一些代码。

为什么要插桩呢?看完生成的代码你就明白了。

我们来格式化一下,把变量名替换下。

这就是转换后的代码,在每一个 statement,每一个 function、每一个 branch 都做了计数,分别是 s、f、b 属性。

上面还有一段代码:

初始化了全局变量 AAA,记录了这些信息:

看到这里我们大概就能搞懂覆盖率的原理了,就是对每个 statement、function、branch 都插入一段计数代码,记录在一个全局对象中。

为了不和别的全局变量冲突,这个对象的名字是随机生成的,比如 __cov_5ZoEXQ_Hbo27uXArxdm2oA,这里为了简化改为了 AAA。

我们搞明白了覆盖率就是靠插入计数代码,那怎么做的插桩呢?

函数插桩

函数插桩是基于 AST,找到 statement、function、branch 的 AST,在前面插入插桩代码的 AST。

istanbul 确实也是这么做的。

下面是 istanbul 的源码(只看红线标出的位置就行):

就是通过 esprima(js parser)来把代码 parse 成 AST,然后对 AST 进行插桩。

插桩代码分为两部分,一部分是初始化全局对象的代码,一部分是每个分支、语句、函数的计数代码。

我们分别来看下:

初始化全局对象的代码插桩

istanbul 初始化了全局的 coverState 对象用于统计:

做插桩的时候会记录信息到这个 coverState 中:

最后把 coverState 变成字符串加入到代码里:

那具体的分支、语句、函数的 AST 是怎么插桩的?

分支、语句、函数的插桩

对不同 AST 的插桩,就是遍历过程中根据类型做不同的处理:

然后,具体的插桩就是在前面插入一段 AST:

statement 插桩:

function 插桩:

看到这里,我们就知道了函数插桩的实现原理,就是遍历 AST,在不同的位置插入计数代码的 AST 就可以了。

但是有的同学可能会说了,平时我也没手动生成插桩后的代码啊?用 jest --coverage 跑测试用例自动就做了计数,然后给出覆盖率数据了。

istanbul 是怎么做到透明的插桩的呢?

require hook 实现透明无感知的函数插桩

看过之前一篇 require hook 的魔术那篇文章的小伙伴知道,nodejs 的模块加载是分为 load、extension['.js']、compile 这几步的。

我们只需要重写 extension['.js'] 这一步,就能做到透明的代码转换。

istanbul 也是这么做的:

它就是通过修改了 extension['.js'] 方法,在这里面做了函数插桩,之后执行的代码就是转换过后的了,开发者根本感知不到。

总结

jest 和 karma 都基于 istanbul 实现了覆盖率检测。覆盖率统计的原理就是函数插桩,基于 AST 在代码的 statement、function、branch 处插入计数代码,同时通过 require hook 实现了透明的转换。这样代码一执行就能拿到统计数据,自然就可以算出覆盖率了。

看完之后,是不是觉得:

覆盖率检测的实现,就这?

 

来源:神光的编程秘籍内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯