使用 JavaScript 写代码的时候,无论是使用 TDD 方法还是为了保证代码的质量和可维护性,都应该考虑加上单元测试。在博文 mocha + chai + Travis CI + Codecov 使用流程 中有简单地介绍了如何使用流行的 JavsScript 库来对代码进行自动测试,检查代码覆盖率。
在那篇文章中,使用的是 Mocha/Chai/istanbul 和在线的 Codecov,以及和 Github 关系密切的 Travis CI,而且测试的 JavaScript 代码是 es5。现在 es2015 已经标准化了,那么教程也需要更新一下了。另外如果项目是私有项目,那么还是使用完备的离线测试环境比较好。接下来就是一个快速可行的教程。
安装和配置
测试框架无需变更,还是 Mocha + Chai 的组合,但是 istanbul 需要稍微变动一下。
如果你不需要 istanbul 做覆盖率测试,那么需要使用
npm install --save-dev babel-register和mocha --require babel-register使 mocha 能识别 es2015 的代码
使用新套件,直接安装 npm i -S mocha chai cross-env nyc babel-plugin-istanbul babel-register babel-preset-env。
mocha 和 chai 不用解释了,nyc 可以理解是 istanbul 的命令行工具;babel-plugin-istanbul 是在 babel 中插入 istanbul,babel-register 是 istanbul 使用的 babel 接口,这样两个库就打通了;最后 babel-preset-env 是 babel 的运行配置。
先来配置 babel-plugin-istanbul,新建 .babelrc:
1 | { |
presets 配置告诉 babel 使用 babel-preset-env。当然也可以用 ‘es2015’ + ‘stage-0’ 的组合,具体可以自行斟酌。
env.test.plugins 告诉 babel 在 NODE_ENV=test 的情况下使用插件 babel-plugin-istanbul。
接下来配置 babel-register,新建 .nycrc:
.nycrc是 nyc 的配置文件,和.babelrc类似,当然配置也是可以直接写进package.json的。
1 | { |
以上的配置直接用了官方的配置。require 字段告诉 nyc 使用 babel-register,reporter 字段的 ‘lcov’ 会让 nyc 生成 lcov.info 文件和对应的 HTML 报告,如果使用 lcovonly 则只生成 ‘lcov.info’。’text-summary’ 则是会在控制台输出覆盖率等信息。
文件会默认生成在
/coverage下,可以使用report-dir字段指定。
最后,在 package.json 中加入:
1 | "scripts": { |
测试编写事例
比如有 index.js:
1 | export class Test { |
那么可以写 test/index.spec.js,可以直接上 ES2015 的语法:
1 | import { expect } from 'chai' |
使用 npm test 运行测试,得到:
1 | > cross-env NODE_ENV=test nyc mocha test/**/*.spec.js |
Bonus
在测试中经常需要测试 promise 等异步操作,虽然 Mocha 库是可以使用回调来完成测试的,但是我们当然要用 async/await 啦。
比如,需要测试 index.js 中的 requestAsync:
1 | export class Test { |
那么需要先 npm i -S babel-polyfill babel-plugin-transform-async-to-generator。
然后配置 .nycrc,加上 ‘babel-polyfill’ 支持 generator 运行时:
1 | { |
配置 .babelrc,加上 ‘transform-async-to-generator’,将 async 模式转换为 generator 模式。
1 | { |
接着这样测试异步:
1 | import { expect } from 'chai' |
在测试项 it 的第二个函数前加 ‘async’ 标志异步,然后在返回 promise 的调用前加上 ‘await’,OK。
1 | > cross-env NODE_ENV=test nyc mocha test/**/*.spec.js |