子曰:Istanbul 与土耳其伊斯坦布尔的联系
最近在读Vuejs 源码的时候,发现有这样的一句话
1 | /* istanbul ignore if */ |
一开始并没有太在意,只是认为这是一个简单的注释,说是伊斯坦布尔忽略if
,但是发现还有
1 | /* istanbul ignore next */ |
这样的语句,于是检索了一下,发现Istanbul 是一个代码覆盖率工具,而上面这些注释,是Istanbul 提供的注释代码,允许某些代码不计入覆盖率。
Istanbul
Istanbul 是JavaScript 程序的代码覆盖率工具。
Istanbul 命名同土耳其的伊斯坦布尔相关的原因是,土耳其地毯闻名世界,而地毯是用来覆盖的。
代码覆盖率(code coverage)
我们在测试时,会关心是否所有的代码都测试到了,而这指标就是“代码覆盖率”。它有四个测量纬度。
- 行覆盖率(line coverage):是否每一行都执行了。
- 函数覆盖率(function coverage):是否每个函数都调用了。
- 分支覆盖率(branch coverage):是否每个if 代码块都执行了。
- 语句覆盖率(statement coverage):是否每个语句都执行了。
入门
使用npm 全局安装
1
npm i -g istanbul
覆盖率测试
编写一个test.js
文件1
2
3
4
5var foo = 1
var bar = 2
if (foo > 0) {
console.log('foo' + (foo + bar))
}使用
istanbul cover
命令1
2
3
4
5
6
7
8
9
10
11
12
13$ istanbul cover test.js
foo3
=============================================================================
Writing coverage object [\coverage\coverage.json]
Writing coverage reports at [\coverage]
=============================================================================
=============================== Coverage summary ===============================
Statements : 100% ( 4/4 )
Branches : 50% ( 1/2 )
Functions : 100% ( 0/0 )
Lines : 100% ( 4/4 )
================================================================================返回结果显示,test.js 有4个语句(statement),执行了4个;有2个分支(branch),执行了1个 (默认还有一个else 分支) ;有0个函数,调用了0个;有4行代码,执行了4行。
这条命令同时还生成了一个 coverage 子目录,宝行
converage.json
,lcov.info
,lcov-report/*html
。其中lcov-report/*html
是可以在浏览器打开的覆盖率报告,其中有详细信息,到底哪些代码没有覆盖到。
忽略某些代码
笔记开始的代码注释,就是Istanbul 提供的注释代码,允许某些代码不计入覆盖率。
- 忽略else 语句这会忽略else 分支(默认还有一个else 分支)
1
2
3
4
5/* istanbul ignore else */
if (foo.hasOwnProperty('bar')) {
// do something
}
` - 忽略if 语句
1
2
3
4/* istanbul ignore if */
if (hardToReproduceError)) {
return callback(hardToReproduceError);
} - 忽略特定的switch case 语句在上例中,
1
2
3
4
5
6switch (foo) {
case 1: /* some code */; break;
/* istanbul ignore next */
case 2: // really difficult to enter in a unit test for some reason
someCode();
}case 2
语句被忽略了 - 忽略UMD 包裹语句整个函数表达式被忽略了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14(function (root, factory) {
;
/* istanbul ignore next */
if (typeof exports === 'object') {
// CommonJS
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory);
} else {
// Browser globals
root.module = factory();
}
})(this, fn);