[jest] 史莱姆也能学会的前端测试

安装

jest的使用依赖nodejs,要先行安装
若使用vue-cli还可以用vue add将其作为vue插件(cli-plugin-unit-jest)使用,即下方第二种方式

方式一

npm install --save-dev jest

方式二

vue add @vue/cli-plugin-unit-jest

不过vue-cli项目创建时就会提供选择,其中勾上jest就会自行配置
项目中使用的就是这种方式,因此本文讲解这种方式,但具体测试写法一致,可作参考

基础讲解

若使用vue-cli且以方式二安装,那么创建项目后目录结构应形如:


其中 /tests/unit 存放的即是测试代码,目前自带一个板子:example.spec.js

打开上述文件,里面内容应是:

import { shallowMount } from '@vue/test-utils'
import HelloWorld from '@/components/HelloWorld.vue'

describe('HelloWorld.vue', () => {
  it('renders props.msg when passed', () => {
    const msg = 'new message'
    const wrapper = shallowMount(HelloWorld, {
      propsData: { msg }
    })
    expect(wrapper.text()).toMatch(msg)
  })
})

shallowMount

挂载一个 Vue 组件,返回一个wrapper
第一个参数是组件,第二个是options对象,用于设置挂载选项,本例中通过propsData为Helloworld传值:msg
还有一个mount,它与shallowMount差别在于shallowMount在渲染组件时不渲染其子组件,避免了子组件可能带来的副作用(比如Http请求等)
ps:import { shallowMount }类似ES6的新语法解构赋值,它用于部分引入,这里指定从'@vue/test-utils'仅导入shallowMount

describe

用于创建一个测试集,第一个参数为本测试集描述字符串,第二个是一个函数
其中包含具体的测试代码(一些it/test块)

it

断言,与describe一样,第一个参数应该是测试描述,第二个是一个函数
其中通常是由expect组成的一个测试用例
ps: 还有一个test,在在Jest中它与it作用一致

wrapper

shallowMount或mount的返回值,它是一个包括了一个挂载组件或 vnode,以及测试该组件或 vnode 的方法
通过它可以使用该组件内定义的变量、方法、根DOM节点等等,同时提供了许多有用的方法供选择节点、触发事件或修改数据

expect

包裹一个变量,通常是由wrapper某个方法或其上选中的节点的方法或属性的返回值
在其上可以调用许多的toXX()方法来进行断言
expect(wrapper.text()).toMatch(msg)
本例中则是判断该组件内部的文本是否匹配msg字符串,其中msg也可以是一个正则表达式
如果不匹配则会抛出错误,该测试不通过

使用

jest默认会递归文件夹找到文件名以 .spec.js.test.js 结尾的文件,把它们作为测试文件。
也可以在 jest.config.jspackage.json(取决于初始化时的选择) 里设置

编写完测试后键入 npm run test:unit 运行测试,(该指令可以在package.json的scripts块中修改)

进阶

建议参阅官方文档https://vue-test-utils.vuejs.org/zh/api/
其中介绍、安装、教程三块为基础使用,可参考
API指'@vue/test-utils'库中那些对象,如mount
关于wrapper及更多选项皆有涉及
同时建议使用vscode或其他能智能提示的编辑器,通过ctrl+左键点击相应函数或对象查看具体代码或更多同类函数,例如toBe、toEqual等等

踩过的坑

  1. 项目中使用了element-ui库的一些组件,一开始一直报错,说组件没注册,后来明白测试js独立于项目与 /src/main.js 一样需要使用Vue.use()注册用到的组件,全局指令Vue.directive等也都要重新定义
  2. 节点渲染时机很难把握,项目中需要先点一个按钮才会渲染第二个按钮,需要测试第二个按下后的变化,那么需要像下面这样:
  wrapper.findAllComponents({ name: 'el-button' }).at(0).trigger('click')
  it('描述', () => {
    wrapper.findAllComponents({ name: 'el-button' }).at(2).trigger('click')
  })

这两个点击不能放一起,不可以同在it外,也不可以在同一个it内,分开就可以...
3. 难以获取组件,去看官方文档会发现wrapper的find与findall都已经标上了Deprecation warning,即不推荐使用,并即将移除,要用findComponent与findAllComponents替代,
然而后面这两个不可以选取原生标签,而且好像也不支持选择器,最后无奈还是上了find,也可能是自己学得还不够
4. 与3同一个问题,多组件只能靠findAllComponents,并且通过.at()来选择其中某一个,然而若是之后代码里多加了个组件,那么整个顺序会乱,测试就得重写,很不舒服

结语

看到这里你已经是个成熟的测试了,可以尝试去大厂投简历,或者为开源社区做贡献,走上人生巅峰

原文地址:https://www.cnblogs.com/Stareven233/p/13807613.html