说明
恕在下时间有限,最近才开始研究单元测试,所以要从头开始搭建一个包括mocha+karma+chai+Sinon这种完整的测试环境实在太过困难,因为目前所使用的开发框架是vue,所以直接使用vue-cli中帮我搭好了的mocha测试环境。这样我们只需要了解该如何使用mocha语法编写单元测试,以及学会使用chai断言库和使用sinon去mock我们的模块来帮我们完成单元测试的编写即可,至于vue-cli中是如何进行配置搭建mocha以及karma的,我们先缓一缓,后续有时间我再研究他们是如何从头搭建的。
ps:经过我踩坑无数,因为vue-cli3.0默认的mocha测试只含有mocha+chai,并没有karma,所以我为了和vue-cli进行整合,比如添加覆盖率功能,生成漂亮的报表功能,vue-cli3.0集成karma等等,配的我怀疑人生,如果在研究测试时能重新选择一次,我一定先研究Jest,因为据说他是零配置,不管是断言,覆盖率什么的都给你集成好了,难受
这里使用的是vue-cli3.0的版本,2.0的在这里注意可能水土不服,如果不熟悉cli的使用,先移步官网官网了解。
运行vue create xxx
命令
在预设中选择Unit Testing
然后在选择测试方案中选择Mocha + Chai
等待安装完毕即可。
|-- 根目录
| |-- tests
| | |-- unit
| | | -- example.spec.js
也就是在根目录中的tests文件夹下的unit的examp.spec.js就是一个测试用例的例子,你所编写的测试用例可以根据功能模块来编写,并根据文件夹进行分门别类,以便后续维护,并且测试用例文件名要以.test.js
或.spec.js
结尾。
在终端中运行如下代码来执行测试:
npm run test:unit
他会执行tests文件夹中的测试用例,并在控制台中打印,结果如下:
HelloWorld.vue
√ renders props.msg when passed (44ms)
1 passing (53ms)
MOCHA Tests completed successfully
在运行默认的vue-cli创建的test命令时,你可以在tests/unit
文件夹中创建任意的测试文件,但是需要注意以下几点:
你创建的测试文件需要以.spec.(js|ts)
结尾,我试过默认的vue-cil命令不能识别以.test.(js|ts)
结尾的测试文件。
运行默认的npm run test:unit
时,他只会查找tests/unit
文件夹下的测试文件。
注意这两点,你就可以编写你的测试用例了,不过,在此之前,我们并不能满足于vue-cli提供的默认测试功能,我们需要让他更加完善,可以支持更多的功能,所以,我们一个个的研究如何扩展我们的测试吧。
vue-cli3.0中,提供了**@vue/cli-plugin-unit-mocha**插件来集成mocha的使用,具体可以查看GitHub。如果你初始化的vue-cli3.0的项目没有选择mocha测试,那么你直接使用cli添加此插件即可:
vue add @vue/unit-mocha
这样就和在一开始使用cli创建vue项目时选择mocha测试一致了。并且,他还会生成tests/unit/example.spec.js
这个测试用例。并且,npm命令也会支持test:unit
命令。
或者你可以直接安装@vue/cli-plugin-unit-mocha
:
npm install --save-dev @vue/cli-plugin-unit-mocha
不过需要做一些额外操作:
你需要自行在根目录下创建tests/unit
及测试用例
你需要手动在package.js
的script
字段中增加"test:unit": "vue-cli-service test:unit"
命令
我测试时他好像没有安装chai断言库,所以我手动安装chai的,如果有一些库没有安装,你可以手动安装一下,与其这么麻烦,所以还是推荐使用直接添加插件的形式安装他较为妥当。
其实英语好的看github上的介绍就好,我这里也看不出什么名堂(原谅我英语太差)。常用的感觉就下面这些:
--watch, -w 运行文件监听模式,当测试用例或者测试用例的依赖文件更改时则重新执行测试。
--grep, -g 只运行匹配的测试
--timeout, -t 测试用例超时时间,默认2000
--bail, -b 当一个测试用例不通过时,后续测试用例无须执行。
而且,上面不够用没关系,他还支持所有的mocha-webpack的命令行参数。其实他的大部分和mocha中的命令行参数是一致的,参考这篇mocha中文翻译,里面有mocha命令行含义的中文翻译:https://www.jianshu.com/p/9c78548caffa
既然如此,我们就使用命令行为我们的测试增加一些新功能。
注意,这里配置的不是mocha的opts文件,所以,不能放在你的test文件夹下,这个mocha-webpack.opts指的是mocha-webpack包的参数配置文件,他默认是放在你的根目录下的,比如:
// mocha-webpack.opts
// 每一条命令占一行,并且应该是按照前后出现进行拼接的
--reporter mochawesome
这样,你就可以把运行的命令中的参数给提取到这里进行维护,当然,你也可以在命令中指定这个参数配置的路径,比如在package.js
中:
"script": {
"test:unit": "vue-cli-service test:unit --opts 配置文件的路径"
}
这样效果其实是一样的。
在vue-cli3.0中,他默认以及安装了chai这个断言库了,直接使用即可,而这里说的这个插件是为了辅助我们的测试的,用途我之前已经介绍过了,这里只介绍如何安装,在后续的使用时我会介绍其用途。
这只是一个辅助工具,所以,不是必须的。
$ npm install --save-dev sinon
然后在编写测试用例时,直接使用即可:
import sinon from 'sinon';
这个vue官方推荐的vue测试工具,使用这个工具可以方便我们测试vue项目,他可以对vue组件进行挂载,模拟事件以及组件的事件,传递参数给组件等等,专门对vue的组件进行测试。vue-cli3.0在安装mocha测试时会自动安装他。
这个插件本篇文章不展开其使用,官网已经有很好的文档说明了,在后续的单元测试编写文章中我再详细展开。
使用这个模块,可以生成漂亮的HTML格式的测试报告,以便你更好的分析你的测试结果。我们在mocha中默认是使用的spec格式的,也就是上文中命令行的测试结果的那种测试报告格式,你可以运行如下命令来查看mocha中支持的测试报告格式:
// 我这里全局安装了一个mocha的,所以才可以直接使用mocha命令查看
mocha --reporters
// 打印
doc - HTML documentation
dot - dot matrix representation
json - single JSON object
json-stream - newline delimited JSON events
landing - Unicode landing strip
list - like "spec" reporter but flat
markdown - GitHub Flavored Markdown
min - essentially just a summary
nyan - "nyan cat"
progress - a progress bar
spec - hierarchical & verbose [默认]
tap - TAP-compatible output
xunit - XUnit-compatible XML output
你可以修改你的vue项目中的package.js文件的test:unit
这个script命令为vue-cli-service test:unit --reporter
来使用不同的测试报告输出格式,不过现在我们还是要使用mochawesome这个插件来生成我们漂亮的报告。
安装
// 局部安装的
npm install --save-dev mochawesome
然后执行如下命令:
$ vue-cli-service test:unit --reporter mochawesome
// 输出:
MOCHA Testing...
testA
√ 测试二
HelloWorld.vue
√ renders props.msg when passed
2 passing (26ms)
[mochawesome] Report JSON saved to D:\工作区\my-project\vue-test-re0\mochawesome-report\mochawesome.json
[mochawesome] Report HTML saved to D:\工作区\my-project\vue-test-re0\mochawesome-report\mochawesome.html
MOCHA Tests completed successfully
可以看到,他会在我们的根目录下生成一个mochawesome-report
文件夹,打开里面的html就可以看到我们漂亮的测试报告了:
他是一个js的代码覆盖测试报告的生成工具,我们使用它配合mocha来生成代码覆盖测试的报告。关于代码覆盖率的了解,参考我另一篇文章的附录。我们通过这个工具来生成我们的代码覆盖率报告,以此来检测我们的测试的好坏。
ps:截止该文章发表时,我还未找到完美集成到vue-cli3.0项目的方法,所以,如果不需要覆盖率报告的,
可以跳过这里
。
注意:不要直接安装istanbul这个npm包,因为它好像属于已经即将废弃的状态了。
我们直接安卓nyc作为我们的项目依赖,他是istanbul的命令行工具,整合了和istanbul有关系的模块,我们只用安装就好:
npm install --save-dev nyc
你可以使用npx nyc --help
来查看帮助。
我们可以直接在package.js的脚本中设置命令(注意:这里并没有使用vue-cil来运行mocha测试,而是直接使用项目依赖中的mocha来执行我们的测试用例)
:
{
"script": {
"coverage": "nyc --reporter=html --reporter=text mocha test.js"
}
}
上诉命令中,--reporter=html
可以在根目录中生成一个coverage文件,里面的index.html是整体覆盖率的统计表格,以测试文件命名的则标注了每个测试文件中哪些地方未覆盖到。--reporter=text
则是执行时会在命令行中打印覆盖率报表。mocha test.js
则是执行的测试,测试文件为test.js
。
// test.js
function test(a) {
if (a) {
return 1;
} else {
return -1;
}
}
describe('testA', () => {
it('测试一', function () {
test(false)
});
})
执行
$ npm run coverage
testA
√ 测试一
1 passing (9ms)
----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 83.33 | 50 | 100 | 83.33 | |
test.js | 83.33 | 50 | 100 | 83.33 | 4 |
----------|----------|----------|----------|----------|-------------------|
根目录下的coverage文件夹中的index.html
根目录下的coverage文件夹中的test.js.html
你可以在package.js
中添加一个nyc的配置,不过建议在根目录增加一个.nycrc
或者nyc.config.js
,我们这里用nyc.config.js
:
// 一些配置
module.exports = {
// 是否测试项目所有文件,而不仅仅是测试套件所接触到的文件
// 如果开启了,那么即使在所有测试用例中都没用到的模块也会列出来,当然,肯定是0的覆盖率了。
all: false,
// 显示覆盖率结果,html表明在项目下生成一个漂亮的html报表,text表示在终端中显示覆盖率结果
reporter: ["html", "text"],
// nyc除了js之外还应该处理的扩展名的列表,比如.ts之类的
extension: [],
// 这是通常对待处理文件进行编译的配置,比如es6语法就要进行babel编译
require: [],
// 这个就是代码映射,默认就是开启的
sourceMap: true,
// 一个需要排除特定文件的列表
exclude: [],
// 一个只需要包含特定文件的列表
include: [],
}
我们把npm中的coverage
命令中执行nyc
的--reporter
参数给提取到nyc.config.js
文件中,这样我们的coverage
命令就变成了:"coverage": "nyc mocha test.js"
因为篇幅问题(其实是英文看不懂),其他参数配置自行参悟,具体请参考官方文档:
GitHub:https://github.com/istanbuljs/nyc
上面的都是独立于vue-cli的mocha测试进行的,而现在需要将nyc同vue-cli的mocha命令进行结合。
我们改一下package.js
的script中的coverage
命令为:nyc vue-cli-service test:unit
。并且我们在npy.config.js
中什么都没有
进行配置,从头开始测试。那么执行如下命令:
$ npm run coverage
// 结果
testA
√ 测试二
HelloWorld.vue
√ renders props.msg when passed (52ms)
2 passing (59ms)
MOCHA Tests completed successfully
----------------------------------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------------------------------------|----------|----------|----------|----------|-------------------|
All files | 90.91 | 50 | 62.5 | 90.91 | |
vue-test-re0 | 100 | 100 | 100 | 100 | |
babel.config.js | 100 | 100 | 100 | 100 | |
postcss.config.js | 100 | 100 | 100 | 100 | |
vue-test-re0/dist/webpack:/(webpack)/buildin | 81.82 | 50 | 25 | 81.82 | |
module.js | 81.82 | 50 | 25 | 81.82 | 10,16 |
vue-test-re0/dist/webpack:/tests/unit | 100 | 100 | 100 | 100 | |
example.spec.js | 100 | 100 | 100 | 100 | |
----------------------------------------------|----------|----------|----------|----------|-------------------|
反正不知道为什么,多出来的东西在我的预料之外,因为我的测试用例文件/tests/unit/example.spec.js
只有一个,不知道其他文件哪来的,可能是在vue-cli-service在执行测试时用到的一些模块吧,比如上面列出了babel.config.js,可能是在编译example.spec.js文件时用的,所以这里也列出来了。
如何解决呢?我们之前在直接使用mocha时,因为测试用例简单,并且也故意没有使用es6语法,所以,可以直接通过,只有一个文件的测试覆盖率,但这里很明显行不通。不太好办。
目前还未研究此具体的办法,所以后续如果找到会进行补齐
如果没有必要,也就是不需要在浏览器上测试,那还是不用这个了,我研究许久,还是无法达到要求,头都大了,所以这里就不把半成品写进来了,后续我单独有空研究完karma再尝试集成到vue-cli3.0看看吧(主要是集成覆盖率那一块没搞定,cli本身集成karma倒是已经找到插件的了)。
如果你用的是vue-cli2.0,那么他的一个选项中已经集成了mocha&karma,所以直接拿来用即可,而3.0需要配合一个插件,而且,麻烦的不在于karma本身,而是当我想要把Istanbul也集成进去时遇到了问题,后续我有空再继续研究他,至少目前不打算在浏览器中测试,暂时放一放吧。
而且,在对于测试vue的单文件组件中,官方并不推荐运行到一个真实的浏览器环境,而是推荐使用JSDOM在node虚拟环境中运行测试。
本篇文章主要简述了如何在vue-cli3.0中进行单元测试,其实如果不在意是不是浏览器中跑测试的话,用不用karma都无所谓,因为可能配置起来比较麻烦,现在只研究到了Unit单元测试,而E2E端对端测试有空我也会进行研究的,后续有空会进行整理。
ps:目前文章发布前,我个人研究后整合到vue-cli3.0的只有mochawesome,karma和测试覆盖率还有问题没有完美的解决,所以关于karma和测试覆盖率的部分如果不需要的可以跳过,仅仅使用mocha+chai+sinon+vue-test-utils进行单元测试的编写即可。这样就简单了很多。