Mocha, chai, sinon and istanbul achieve 100% unit test coverage

In agile software development, the most important practice is test-driven development. At the unit testing level, an important indicator we try to achieve is test coverage. Test coverage measures whether our code has been fully tested.

But the indicator itself is not the purpose. With the test coverage check, we hope to find the code that is not covered by the test, so as to think about how to test the logic of those code, and then better design and refactor the code, so that the code has a higher quality.

Speaking of tests, I just recently read "The Beauty of Mathematics", a passage about information in the book. We want to change the behavior of the code from non-deterministic to deterministic, the same is true. From a black box to a white box, there is no magic power, only enough information is provided, and the assertion in the test is the information, and the test coverage is also the information. The test coverage can be considered as an indirect information, which can eliminate part of the information. Uncertainty, while full assertion, provides more direct information. Combined with test coverage checks, this provides enough information to assert that the code is behaving as expected.

Test related technologies

Istanbulis the JavaScriptprogram's code coverage tool named after Istanbul, Turkey's largest city. Istanbul will convert the code, generate a syntax tree, and then inject the statistical code in the corresponding position. After execution, according to the value of the injected global variable, count the number of times the code is executed; after the conversion of the code is completed, Istanbul will call test runner, for example mocha, execute Test the converted code and generate a test report.

MochaIt is a testing framework, that is, a tool for running tests, similar to Jasmine, Karma and Ava. Like JUnit's annotations, mocha acts as an executor, using descibeand itmethods, to define test suits and group different tests. mocha itself does not provide assertassertions, so to provide more expressive assertions, you can chaiuse them together, and of course you can use the ones provided by nodejs assert模块.

In our code, there will always be some complex logic or asynchronous code that depends on io and network, which is difficult to test with direct methods. At this time, we can sinonsimplify the test of complex code. By creating a Test Double测试替身 , Sinon replaces some functions or classes that our code depends on with a test double, and we can set the behavior of the test double to simulate the results our code needs, so that the code logic that is difficult to test be executed.

Configure test environment for nodejs project

1 Install the corresponding dependencies

mocha and istanbul can be installed globally or only in the current project.

npm install --save-dev mocha chai sinon istanbul

After the installation is complete, under package.jsonthe scripts of the file, add commands to perform tests and test coverage checks

{
  ...
  "scripts":{
    "coverage": "istanbul cover _mocha -- -R spec --timeout 5000 --recursive",
    "coverage:check": "istanbul check-coverage", } ... }

Run npm run coverageand npm run coverage:check, you can generate a test report, the former generates a test report, and the latter checks whether the test coverage meets the requirements.

<iframe id="iframe_0.48200238053686917" style="margin: 0px; padding: 0px; border-style: none; width: 592px; height: 289px;" src="data:text/html;charset=utf8,%3Cstyle%3Ebody%7Bmargin:0;padding:0%7D%3C/style%3E%3Cimg%20id=%22img%22%20src=%22http://upload-images.jianshu.io/upload_images/1400900-2fd5d2f1edc17fd6.png?imageMogr2/auto-orient/strip%257CimageView2/2/w/1240&_=7146503%22%20style=%22border:none;max-width:669px%22%3E%3Cscript%3Ewindow.onload%20=%20function%20()%20%7Bvar%20img%20=%20document.getElementById('img');%20window.parent.postMessage(%7BiframeId:'iframe_0.48200238053686917',width:img.width,height:img.height%7D,%20'http://www.cnblogs.com');%7D%3C/script%3E" frameborder="0" scrolling="no"></iframe>

2 Configure Istanbul

istanbul相关的执行参数,可以在命令行下执行时传递参数来制定,也可以在yaml格式的.istanbul.yml文件中配置。简单贴出一些重要的配置项

instrumentation:
  root: .   # 执行的根目录
  extensions:
 - .js # 检查覆盖率的文件扩张名  excludes: ['**/benchmark/**'] ... ... reporting:  print: summary  reports: [lcov, text, html, text-summary] # 生成报告的格式  dir: ./coverage # 生成报告保存的目录  watermarks: # 在不同覆盖率下会显示使用不同颜色  statements: [80, 95] ... ... check:  global:  statements: 100  branches: 100  lines: 100  functions: 100

最后的check是项目要通过覆盖率检查需要达到的测试覆盖率,测试覆盖率包括四个维度,分别是语句覆盖率、分支覆盖率、行覆盖率和函数覆盖率。如果达不到设定的指标,在执行的时候会报错,项目的测试就无法通过自动化的持续集成。

编写测试代码

敏捷软件开发中的测试驱动开发,意在通过先写测试,根据调用者的契约,设计如何实现代码,从而写出更加容易测试的代码,提高代码的质量。也是我们练习测试的应该考虑的方向。

1 一段简单的mocha测试代码

利用chai提供的expect断言,我们可以用BDD的方式,写出更加符合代码预期行为的测试用例。

var chai = require('chai')

chai.should()
var expect = chai.expect
var assert = chai.assert describe('basic test', function () { describe('simple', function () { it('data check', function () { var data = { name: "test" } assert.isNotNull(data, 'data should not be null') expect(data).to.be.an('object') expect(data).to.have.all.keys(['name']) expect(data).to.deep.include({name: 'test'}); }); }); });

2 用Sinon模拟文件读写

... 同上 ...
var sinon = require('sinon')
var fs = require('fs') describe('sinon', function () { it("should mock readFile", function(done){ sinon.stub(fs, 'readFile').callsFake(function (path, callback) { callback(new Error('read error')) }) fs.readFile("any file path", function(err,data){ assert.isNotNull(err) done() }) assert(fs.readFile.calledOnce) }); });

在mocha测试框架中,如果我们调用的是异步的代码,那么需要显示的调用it回调函数的done方法,告诉mocha异步调用什么时候结束。否则的话,测试会挂起,直到设置的超时时间结束。

Sinon将测试替身分为spy、stub和mock,其中:

  • Spy, 可以提供函数调用的信息,但不会改变函数的行为
  • Stub, 提供函数的调用信息,并且可以像示例代码中一样,让被stubbed的函数返回任何我们需要的行为。
  • Mock, 通过组合spies和stubs,使替换一个完整对象更容易。

本文的讨论篇幅有限,暂时不详细介绍各种sinon的使用方法,以后再通过其他文章专门介绍。

持续集成

完成所有代码之后,我们可以将代码发布到github,然后使用持续集成工具travis检查代码,将生成的测试报告上传到coverall上,这样就可以在项目中显示项目状态和测试覆盖率的badges。

具体使用方法,可以参看官方网站,使用coveralls需要在项目中安装依赖包npm i -D coveralls。并且添加package.json执行脚本istanbul cover ./node_modules/mocha/bin/_mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js

通常的nodejs项目.travis.yml配置如下:

language: node_js
node_js:
  - "7.6.0"
install:  - npm install script:  - npm test after_script:  - npm run coverall

 

 

原文地址:http://www.51test.space/archives/2543

更多软件测试相关信息:  www.51test.space
欢迎关注公众号 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326563741&siteId=291194637