记录在往 vue+webpack 的项目中添加 jest 单元测试时遇到的坑。
安装
很简单,直接按照jest 官网来即可:
1 | yarn add --dev jest |
然后在package.json
添加一个script
即可,如:
1 | "utest": "jest" |
之后按照官网上所述编写一个简单的测试文件就能跑起来了。本文剩下的篇幅都是记录在结合 Vue 时遇到的坑。
配置
在我们项目中都是使用 vue 的单文件系统,每个组件后缀名是.vue
,同时也经常import
各种js
模块,还会有一些json
文件。默认情况下jest
对于一个没有后缀名的import
语句无法解析的,如:
1 | import pageTitle from 'src/components/container/page-title'; // 导入一个vue组件 |
需要进行一些配置。 同时还有一些其他的配置需要添加,例如配合webpack alias
。
jest
中的配置文件很简单,只要在项目根目录添加一个jest.config.js
即可,目前我们项目中的配置如下:
1 | module.exports = { |
vscode 调试
有时候测试失败不知道是因为业务代码有 bug 还是因为测试代码本身有 bug,此时调试功能就很有用,在 vscode 下可以通过一段配置即可支持调试,参考 how-to-debug-jest-tests-with-vscode:
将下面代码放到项目.vscode/launch.json
的configurations
数组中:
1 | { |
之后就可以打断点调试了:
jest wacth 问题
默认情况下npm run utest
跑完测试就会结束,下一次需要重新运行命令再跑,很麻烦。 jest
提供了watch
选项,可以每次在改动了测试代码后自动重跑测试:
1 | npm run utest -- --watch |
不过遇到奇怪的问题,总是会卡在Determining test suites to run…
,除非强行退出:
暂时使用了另一个watchAll
选项规避了,npm run utest -- --watchAll
, 也可以 之后有空再研究怎么解决吧。。
element-ui
项目中使用了一些element-ui
的组件,在带有这些子组件的组件时,会报错子组件找不到,网上的解决方案时使用 localVue 来安装element-ui
:
1 | localVue = createLocalVue(); |
不过在尝试时发现报了另一个错:
看起来是解析 css 时出错,解决方案是添加jest 官网给的一段配置到jest.config.js
中:
1 | // for CSS Modules |
bui 组件库问题
项目中使用了内部的bui
组件库,它不是通过npm
安装的,而是直接外链script
引入,这会导致在测试使用了bui
组件的 vue 文件时,提示bui
组件找不到:
一开始的思路是跟element-ui
一样解决,不过发现bui
的install
过程是在引入外链时自动执行了:
bui/src-latest/index.js
1 | function install(Vue) { |
解决办法是利用vue-test-util
的stub
vue-test-util
这是一个帮助我们更快编写测试代码的库,提供了很多便利方法,具体参见官方文档。
在实例化组件时,对于组件内部的子组件,如果不想导入它们可以利用stub
选项。它类似于 mock 一个子组件,可以给它提供一个很简单的实现即可。
例如对于我们的某个 bui 组件byted-progresss
,可以直接利用一个空的<div />
:
1 | wrapper = shallowMount(comp, { |
其他类似,此时再跑单元测试的话应该就没问题了。
如果不想用空的div
代替,可以手动import
每个bui
组件,然后 stub 它们:
1 | import Button from 'bui/src-latest/components/button'; |
不过这种方式仍然对于某些 bui 组件会失败,因为那些组件内部使用了Vue
对象,默认是在window
对象上,而在单元测试的 node 环境中没有这个对象。尝试显式使用gblobal.Vue = localeVue
也没有完全解决。
snapshot
snapshot 是jest
一项很有用的功能,用来查看在运行某项测试时的 UI 结构快照,这样可能帮助我们找到测试失败的原因,具体参照官网教程
每个 snapshot 创建完之后,会在__snapshot__
文件夹中生成一个文件。
例如我写了一个测试:
1 | it('has the expected html structure', () => { |
跑完这个生成的文件如下:
所有子组件如果默认情况下都是空的,组件名后面添加了-snapshot
,被显式stub
了的都有具体的dom
结构。
CI
如果直接利用了bui
组件的定义来 stub,在集成单元测试到gitlab ci
上时会出问题,因为无法在 ci 机器上安装 bui,bui 没有提供https
的下载链接:
目前的解决方案是自己写一个很简单的组件来stub
。最后贴一下 ci 的配置,在项目根目录的.gitlab-ci.yml
中:
1 | image: node:8.6 |
其他
对于如何写单元测试,自己也才刚刚开始,不过参考了这个文档:
参考文档
- https://github.com/facebook/jest
- https://github.com/facebook/jest/blob/master/docs/Webpack.md
- https://medium.com/@mattmazzola/how-to-debug-jest-tests-with-vscode-48f003c7cb41
- https://vue-test-utils.vuejs.org
- https://jestjs.io/docs/en/jest-object
- https://alexjoverm.github.io/2017/08/21/Write-the-first-Vue-js-Component-Unit-Test-in-Jest/