You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
? 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
:The text was updated successfully, but these errors were encountered: