Fork me on GitHub

macha+istanbul+chai到ava+istanbul+nyc

从一个npm包开始

本系列主要想记录一下如何在发布之前测试一个简单的工具包,为这个npm工具包实现完善的单例测试,从而为今后可以扩展到其他更复杂的测试体系打好基础。

新建项目

1
2
mkdir aegis_utils && cd aegis_utils
npm init

可以使劲按enter,或者填写一些自己的想要填写的信息,
最终得到如下package.json文件:

1
2
3
4
5
6
7
8
9
10
11
{
"name": "aegis_utils",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

入口文件index.js

入口文件是index.js,在里面写一个工具函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
countNum: (str) => {
const e = [];
const a = [...new Set(str.replace(/\s+/g, '').split(''))].map((row) => {
const reg = new RegExp(row, 'g');
return {
key: row,
value: str.match(reg).length
};
});
a.map(row => row.value === Math.max(...a.map(row => row.value)) ? e.push(row.key) : null);
return e;
},
}

选择测试框架组合

这里我先后使用了两种组合来实现测试,一个是mocha+chai+istanbul,一个是ava+chai+nyc.下面分开来讲。

mocha+chai+istanbul

执行安装命令,这里都使用本地安装,避免出现不可描述的错误。

1
npm i -D mocha istanbul chai

package.json里面修改字段test命令,mocha默认执行test文件里面的测试用例,最简单的使用方法是直接mocha,当然是在全局安装的情况下。

1
"test": "node ./node_modules/mocha/bin/mocha",

新建测试文件

根目录下新建test文件夹,新建utils.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const chai = require('chai');
const utils = require('../index.js');
const expect = chai.expect;
// countNum
describe('countNum:找出字符串中字符数最多的那个字符,不包括空格', function () {
describe('找出字符串中字符数最多的那个字符', function() {
it('should return l', function() {
expect(utils.countNum('hello world')[0]).to.eq('l');
})
});
describe('有相同个数的最多的字符串', function() {
it('should return 3', function() {
expect(utils.countNum('hh ee llo').length).to.eq(3);
})
});
});

执行npm test,得到

20171128_1.png

因为想要在测试案例里面使用es6语法的模块导入import等功能,可以添加.babelrc配置,安装babel相关插件

1
npm i -D babel-core babel-preset-stage-2 babel-preset-es2015 babel-plugin-transform-runtime
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"presets": [
"es2015",
"stage-2"
],
"plugins": [
[
"transform-runtime",
{
"helpers": false,
"polyfill": true,
"regenerator": true,
"moduleName": "babel-runtime"
}
]
],
"comments": false
}

修改package.json里面的test script为

1
"test": "babel-node ./node_modules/mocha/bin/mocha --compilers js:babel-core/register",

修改test/utils.js文件,可以使用es6语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import chai from 'chai';
import utils from '../index.js';
const expect = chai.expect;
// countNum
describe('countNum:找出字符串中字符数最多的那个字符,不包括空格', () => {
describe('找出字符串中字符数最多的那个字符', () => {
it('should return l', () => {
expect(utils.countNum('hello world')[0]).to.eq('l');
})
});
describe('有相同个数的最多的字符串', () => {
it('should return 3', () => {
expect(utils.countNum('hh ee llo').length).to.eq(3);
})
});
});

执行npm test,得到同上结果.

istanbul生成测报告

本地安装istanbul, 额,之前安装过了。package.json里面添加script命令

1
"cover": "babel-node ./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- --compilers js:babel-core/register -R spec --timeout 5000 --recursive",

执行npm run cover,会发现,测试成功,但是,输出一句话:

No coverage information was collected, exit without writing coverage information

google了一下发现是istanbul的版本问题,需要安装1.1.0-alpha.1版本

1
npm i -D istanbul@"1.1.0-alpha.1"

然后再执行npm run cover,会发现,测试成功,而且根目录下生成了coverage目录,

20171128_2.png

里面找到index.html文件,浏览器打开即是生成的测试报告。

20171128_3.png

点击具体的文件可以查看文件的覆盖率,红色表示为覆盖到的代码。自己体验吧。
https://zp1112.github.io/ava-practice/coverage/lcov-report/index.html

mochawesome生成美丽的详尽的测试案例报告

使用mochawesome可以生成漂亮的 HTML 格式的模块,npm i -D mochawesome安装好后,package.json里面新增字段

1
"mochawesome": "node ./node_modules/mocha/bin/mocha --compilers js:babel-core/register --reporter mochawesome"

执行npm run mochawesome,在根目录下生成mochawesome-report文件夹,里面的mochawesome.html浏览器打开,得到

20171128_5.png

https://zp1112.github.io/ava-practice/mochawesome-report/mochawesome.html
这是test命令其实可以去掉了。

ava+chai+nyc

执行安装命令,这里都使用全局安装,避免出现不可描述的错误。

1
npm i -g ava nyc

package.json里面配置ava和nyc选项,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
"ava": {
"files": [
"ava/*.js",
"!**/not-this-file.js"
],
"require": [
"babel-register"
],
"babel": "inherit"
},
"nyc": {
"lines": 95,
"functions": 90,
"branches": 90,
"check-coverage": true,
"report-dir": "./.nyc_output",
"exclude": [
"lib",
"ava",
"coverage",
"test",
"test{,-*}.js",
"**/*.test.js",
"**/__tests__/**"
]
},

新建测试文件

先在根目录下新建ava文件夹,里面新建测试文件utils.js。

1
2
3
4
5
6
7
import test from 'ava';
import utils from '../index.js';
// countNum
test('countNum:找出字符串中字符数最多的那个字符,不包括空格', t => {
t.is(utils.countNum('hello world')[0], 'l');
});

执行ava -vsw,(展示详细信息-v,按顺序执行测试案例-s,实时监控测试文件变化和源文件变化-w, 只实时监控源文件变化-S),得到美丽的输出:

20171128_4.png

nyc生成测报告

package.json新增字段

1
"cover-nyc": "nyc ava -vs && nyc report --reporter=html",

执行npm run cover-nyc,即可看到根目录下生成.nyc_output,

20171128_6.png

浏览器打开里面的index.html即可看到详细测试报告

20171128_3.png

总结

以上分别使用了两种测试框架的组合,个人更倾向于ava+nyc的模式,至于ava的好处,可以在这里查看

AVA实践:面向未来的测试运行器

发布

最后写好工具库,再写好测试用例以后,就可以愉快的发布了,至于怎么发布?,好累,不想写了,自行谷歌吧。

发布之前整理一哈package.json里面的npm相关的信息,添加相关字段

1
2
3
4
5
6
7
8
9
10
11
12
13
"repository": {
"type": "git",
"url": "git+https://github.com/yourgitname/yourrepo.git"
},
"keywords": [
"javascript"
],
"author": "yourname",
"license": "ISC",
"bugs": {
"url": "https://github.com/yourgitname/yourrepo/issues"
},
"homepage": "https://github.com/yourgitname/yourrepo#readme",

github源码地址,如果您是初学者,且觉得有些许的帮助,欢迎star支持一下。如果有什么问题,欢迎提issue,一起学习和进步。谢谢大家。

-------------本文结束感谢您的阅读-------------
如果您觉得受益了,欢迎打赏鼓励。