? Check the features needed for your project:
◉ Babel
◯ TypeScript
◯ Progressive Web App (PWA) Support
◯ Router
◯ Vuex
◯ CSS Pre-processors
◯ Linter / Formatter
◉ Unit Testing
◯ E2E Testing
选择 Jest:
? Pick a unit testing solution:
Mocha + Chai
❯ Jest
选择 In dedicated config files 将各配置信息配置在对应的 config 文件里:
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? (Use arrow keys)
❯ In dedicated config files
In package.json
输入n,不保存预设:
? Save this as a preset for future projects? (y/N) n
介绍
Vue-Test-Utils
是Vue.js
官方的单元测试实用工具库,它提供了一系列的API
来使得我们可以很便捷的去写Vue
应用中的单元测试。主流的单元测试运行器有很多,比如
Jest
、Mocha
和Karma
等,这几个在Vue-Test-Utils
文档里都有对应的教程,这里我们只介绍Vue-Test-Utils + Jest
结合的示例。环境配置
通过脚手架
vue-cli
来新建项目的时候,如果选择了Unit Testing
单元测试且选择的是Jest
作为测试运行器,那么在项目创建好后,就会自动配置好单元测试需要的环境,直接能用Vue-Test-Utils
和Jest
的API
来写测试用例了。但是新建项目之初没有选择单元测试功能,需要后面去添加的话,有两种方案:
第一种配置:
直接在项目中添加一个
unit-jest
插件,会自动将需要的依赖安装配置好。第二种配置:
这种配置会麻烦一点,下面是具体的操作步骤。
安装依赖
安装
Jest
和Vue Test Utils
安装
babel-jest
、vue-jest
和7.0.0-bridge.0
版本的babel-core
安装
jest-serializer-vue
配置 Jest
Jest
的配置可以在package.json
里配置;也可以新建一个文件jest.config.js
, 放在项目根目录即可。这里我选择的是配置在jest.config.js
中:各配置项说明:
moduleFileExtensions
告诉Jest
需要匹配的文件后缀transform
匹配到.vue
文件的时候用vue-jest
处理, 匹配到.js
文件的时候用babel-jest
处理moduleNameMapper
处理webpack
的别名,比如:将@
表示/src
目录snapshotSerializers
将保存的快照测试结果进行序列化,使得其更美观testMatch
匹配哪些文件进行测试transformIgnorePatterns
不进行匹配的目录配置 package.json
写一个执行测试的命令脚本:
第一个测试用例
为了保证环境的一致性,我们从创建项目开始一步一步演示操作步骤。
用 vue-cli 创建一个项目
当前我用到的是
3.10.0
版本的vue-cli
。开始创建项目:选择
Manually select features
进行手动选择功能配置:勾选
Babel
、Unit Testing
:选择
Jest
:选择
In dedicated config files
将各配置信息配置在对应的config
文件里:输入n,不保存预设:
项目创建完成后,部分文件的配置信息如下:
babel.config.js
:jest.config.js
, 这个文件的配置默认是预设插件的,可以按实际需求改成上面提到的配置Jest
里的配置一样。package.json
:执行测试命令
用上面的步骤创建的项目完成项目后,我们可以在
package.json
的scripts
项中看到有个test:unit
,执行它:然后终端里会看到输出结果,
PASS
表示测试用例通过了,这个是官方提供单元测试例子。下面我们来写点自己的东西。实现一个 ToDoList
看上面的原型图,有这么几点明确的需求:
-
号表示,点击后删除该项√
号表示,点击后当前项移动到已完成列表x
号表示,点击后当前项移动到未完成列表先把上面的页面写好
写页面之前先把创建项目的时候生成的
HelloWorld.vue
和对应的测试文件example.spec.js
删除;同时修改App.vue
文件,引入ToDoList
组件:在
src/compoents
下新建一个文件ToDoList.vue
,样式较多就不贴出来了,具体可以去看本项目源码:页面写完,原型上的需求也大概开发完成,页面大概长如下样子:
修改目录配置
接下来就是开始编写单元测试文件了,写之前我们先把测试文件目录修改下为
__tests__
,同时修改jest.config.js
为如下配置,注意其中的testMatch
已经修改为匹配__tests__
目录下的所有.js
文件了。编写测试文件
在
__tests__/unit/
目录下新建文件todolist.spec.js
,我们约定测试某个vue
文件,那么它的单元测试文件习惯命名成*.spec.js
或*.test.js
。上面这个测试文件简要说明:
shallowMount
将会创建一个包含被挂载和渲染的Vue
组件的Wrapper
,只存根当前组件,不包含子组件。describe(name, fn)
这边是定义一个测试套件,test ToDoList
是测试套件的名字,fn
是具体的可执行的函数it(name, fn)
是一个测试用例,输入框初始值为空字符串
是测试用例的名字,fn
是具体的可执行函数;一个测试套件里可以保护多个测试用例。expect
是Jest
内置的断言风格,业界还存在别的断言风格比如Should
、Assert
等。toBe
是Jest
提供的断言方法, 更多的可以到Jest Expect
查看具体用法。待完成和已完成列表,居然是列表,所以存放数据的字段必须是
Array
类型,空列表就是空数组。如果第二个测试用例改成:将会报错,因为
toBe
方法内部是调用Object.is(value1, value2)
来比较2个值是否相等的,和==
或===
的判断逻辑不一样。显然Object.is([], [])
会返回false
。setValue
可以设置一个文本控件的值并更新v-model
绑定的数据。.to-do-text
是一个CSS
选择器;Vue-Test-Utils
提供了find
方法来通过查找选择器,来返回一个Wrapper
;选择器可以是CSS
选择器、可以是Vue
组件也可以是一个对象,这个对象包含了组件的name
或ref
属性,比如可以这样用:wrapper.find({ name: 'my-button' })
wrapper.vm
是一个Vue
实例,只有Vue
组件的包裹器才有vm
这个属性;通过wrapper.vm
可以访问所有Vue
实例的属性和方法。比如:wrapper.vm.$data
、wrapper.vm.$nextTick()
。trigger
方法可以用来触发一个DOM
事件,这里触发的事件都是同步的,所以不必将断言放到$nextTick()
里去执行;同时支持传入一个对象,当捕获到事件的时候,可以获取到传入对象的属性。可以这样写:wrapper.trigger('click', {name: "bubuzou.com"})
先用
setData
给toDoList
设置一个初始值,使其渲染出一个列表项;然后找到这个列表项,用setValue
给其设置值,模拟了编辑;列表项的输入框是用:value="item"
绑定的value
, 所以setValue
无法触发更新;只能通过trigger
来触发更新toDoList
的值。一个测试用例中可以写多个
expect
以保证断言的准确性。异步测试
最后我们为了模拟异步测试,所以加一个需求,即页面加载的时候会去请求远程待完成列表的数据。 在项目根目录新建
__mocks__
目录,同时新建axios.js
:修改
ToDoList.vue
,导入axios
和增加mounted
:测试用例编写为:
对于异步的代码,写断言的时候需要放在
wrapper.vm.$nextTick()
里,且手动调用done()
。配置测试覆盖率
测试用例写了部分,如果我们看下覆盖率如何,就需要要配置测试覆盖率。在
jest.config.js
里新增配置:在
package.json
的scripts
中新增一条配置:然后我们在终端运行:
npm run test:cov
,结果如下:运行测试覆盖率命名后会在项目根目录生成
coverage
目录,浏览器打开里面的index.html
: