黎清龙

2个月前
  • 519

    浏览
  • 0

    评论
  • 0

    收藏

代码覆盖率工具 istanbul

本文作者:imweb 黎清龙 原文出处:imweb社区 未经同意,禁止转载

代码覆盖率工具 istanbul

1. 代码覆盖率

在测试时,我们的用例把所有代码都覆盖了吗? 对于这个问题引出了代码覆盖率的测试指标,一共有以下4种:

  • 行覆盖率(line coverage):是否每一行都执行了?
  • 函数覆盖率(function coverage):是否每个函数都调用了?
  • 分支覆盖率(branch coverage):是否每个if代码块都执行了?
  • 语句覆盖率(statement coverage):是否每个语句都执行了?

istanbul 是一个代码覆盖工具

它可以帮助我们检查代码的覆盖率

在一个项目中,可以通过 istanbul 设定某些覆盖率阈值来保证测试用例的齐全完整程度,用来保证代码质量

下面是对 istanbul 的使用&学习所得

2. 安装

需要安装 mocha,should,istanbul

$ npm install mocha
$ npm install should
$ npm install istanbul

mocha 是测试框架,should 是断言库

3. 初探代码覆盖

先来看看我们的测试文件:

// index.js
function add(a, b) {
  a = a || 0;
  b = b || 0;
  return a + b;
}

add(1, 2);

很简单的一个两位数相加的函数,好,我们执行命令:

$ .\node_modules\.bin\istanbul cover index.js

得出下面的结果:

============ Coverage summary ============
Statements   : 100% ( 5/5 )
Branches     : 50% ( 2/4 )
Functions    : 100% ( 1/1 )
Lines        : 100% ( 5/5 )
==========================================

可以看到,列出了4个覆盖率指标的结果

结果表示,语句,代码行还有函数都是100%执行了,但是并不是所有分支都执行过了

那么具体哪些分支没有被执行?

我们可以通过自己肉眼去查看,并且通过大脑去“执行”代码,这是笨方法

istanbul 给我们提供了一个直观的查看结果的方式:网页版结果报告

在执行了命令之后,在当前目录你会发现新生成了一个文件夹:coverage

这个文件夹下面包含了代码覆盖率结果文件以及代码覆盖率结果报告

直接打开coverage/lcov-report/index.html,会在浏览器看到以下页面:

这个页面通过一个很直观的方式来展示每个文件夹下面的文件的代码覆盖率

点击文件夹,可以看到每个具体的文件的代码覆盖率情况:

点击文件名,我们就可以看到该文件的源代码,以及一些代码未有覆盖的情况:

可以看到上面有两个地方标了黄色,也就是说代码没有执行到那些地方

3.1 初探小结

  • 代码覆盖率不一定是要在测试当中,只是通常代码覆盖率用于测试
    • 对于一些自启动的模块,是可以通过代码覆盖率工具去检查代码的执行情况,通过这个方式去查找一些冗余的代码,比如一些永远都不会被执行到的代码
    • 对于非自启动的模块,比如一些库,他们都是被其他代码调用的,这个时候就需要用到单元测试了;单元测试的本质就是测试验证某个模块是否正确可用,它通过创建一些模块依赖的stub,并且编写启动代码去调用模块的接口来完成这个目标;通过代码覆盖率工具,我们可以知道测试用例是否齐全,覆盖到了“足够多”的代码
  • 4个指标当中,行覆盖率和语句覆盖率很相近;在代码规范的情况下,它们应该是一样的,因为我们规范要求一行写一个语句
  • 4个指标当中,分支覆盖率是最重要的,它包括:
    • !, &&, ||, ?:
    • ifelse
    • switch - case
    • 等等各种包含分支的情况

4. 配合测试

还是刚刚的例子,这次我们改一下:

// index.js
function add(a, b) {
  a = a || 0;
  b = b || 0;
  return a + b;
}

module.exports = add;

这样,我们就得到了一个非自启动的模块

那么,我们需要编写单元测试:

var should = require('should');
var add = require('./index');

describe('add', () => {
  it('1 + 2', () => {
    add(1, 2).should.be.equal(3);
  });
});

然后我们执行命令:

$ .\node_modules\.bin\istanbul cover .\node_modules\mocha\bin\_mocha -- test.js

结果如下:

============ Coverage summary ============
Statements   : 100% ( 10/10 )
Branches     : 50% ( 2/4 )
Functions    : 100% ( 1/1 )
Lines        : 100% ( 10/10 )
==========================================

注意:这里结果和之前不一样是因为这里还统计了测试用例自身的代码覆盖率情况

这是在 windows 系统,所以需要用 .\node_modules\mocha\bin\下面的 mocha

mocha 前面加的下划线是不能省略的

因为,mocha_mocha 是两个不同的命令,前者会新建一个进程执行测试,而后者是在当前进程(即 istanbul 所在的进程)执行测试,只有这样, istanbul 才会捕捉到覆盖率数据。其他测试框架也是如此,必须在同一个进程执行测试

-- 后面的部分,都会被当作参数传入 mocha 。如果不加,它们就会被当作 istanbul 的参数

4.1 检测代码覆盖率阈值

执行下面命令:

$ .\node_modules\.bin\istanbul check-coverage --statement 90 --branch 90 --function 90

这行命令的意思是检查代码覆盖率结果是否超过阈值指标,这里设置了指标是:语句覆盖率要超过 90%,分支覆盖率要超过 90%,函数覆盖率要超过 90%

结果如下:

ERROR: Coverage for branches (50%) does not meet global threshold (90%)

结果提示说分支覆盖率没有打到指标。。。

4.2 新增测试用例

通过查看代码覆盖率结果报告,知道我们忽略了哪些分支情况后,我们就要需要添加新的测试用例去覆盖这些情况:

var should = require('should');
var add = require('./index');

describe('add', () => {
  it('1 + 2', () => {
    add(1, 2).should.be.equal(3);
  });

  it('1 + undefined', () => {
    add(1).should.be.equal(1);
  });

  it('undefined + 2', () => {
    add(undefined, 2).should.be.equal(2);
  });
});

这次我们再执行代码覆盖率检查命令:

$ .\node_modules\.bin\istanbul cover .\node_modules\mocha\bin\_mocha -- test.js

会得到这样的结果:

============ Coverage summary ============
Statements   : 100% ( 14/14 )
Branches     : 100% ( 4/4 )
Functions    : 100% ( 1/1 )
Lines        : 100% ( 14/14 )
==========================================

这一次,我们再执行代码覆盖率阈值检测命令:

$ .\node_modules\.bin\istanbul check-coverage --statement 90 --branch 90 --function 90

就不会有报错信息了

5 小结

在真实项目中,代码覆盖率工具可以帮助我们完善测试用例,保证代码及项目的质量

通常在测试自动化的基础上,我们再加上代码覆盖率的自动化阈值检测,用来保证测试用例的完整性

0 条评论