vue 环境
在 vue 使用场景下,无非就是组件库和业务逻辑,组件库偏向于 unit 测试,业务逻辑偏向于 e2e 测试,当然两者并不冲突
unit 测试
推荐神器:vue-test-utils
README 给了多个测试库配置的例子,这里还是推荐使用 jest,给个例子
export default { props: ['value'], data () { return { currentValue: 0 } }, watch: { value (val) { this.currentValue = val } } } |
测试如下
import { mount } from '@vue/test-utils' import Test from './Test.vue' test('props value', () => { const options = { propsData: { value: 3 } } const wrapper = mount(Test) expect(wrapper.vm.currentValue).toBe(3) }) |
十分简单的例子,亮点在测试文件的 wrapper 上,通过 mount 方法创建了一个组件实例,创建过程中允许加入一些配置信息,甚至是 mock 组件中的 method 方法
vue 单元测试的范围仅限于数据流动是否正确,逻辑渲染是否正确(v-if v-show v-for),style 和 class 是否正确,我们并不需要关系这个组件在浏览器渲染中的位置,也不需要关系对其它组件会造成什么影响,只要保证组件本身正确即可,前面说的断言,vue-test-utils 都能提供对应的方案,总体上节约很多测试成本
e2e 测试
也是推荐尤大基于最新脚手架的 @vue/cli-plugin-e2e-nightwatch
e2e 测试的重点在于判断真实 DOM 是否满足预期要求,甚至很少出现 mock 场景,不可或缺的是一个浏览器运行环境,具体细节不赘述,可以看官方文档。
nuxt 服务端渲染环境
nuxt 官方推荐 ava,顺势带出 ava 的方案
unit 测试
麻烦在配置上面,先给出需要安装的依赖
"@vue/test-utils", "ava", "browser-env", "require-extension-hooks", "require-extension-hooks-babel", "require-extension-hooks-vue", "sinon" |
在 package.json 里加几行 ava 配置
"ava": { "require": [ "./tests/helpers/setup.js" ] } |
下面来写 ./tests/helpers/setup.js
const hooks = require('require-extension-hooks') // Setup browser environment require('browser-env')() // Setup vue files to be processed by `require-extension-hooks-vue` hooks('vue').plugin('vue').push() // Setup vue and js files to be processed by `require-extension-hooks-babel` hooks(['vue', 'js']).plugin('babel').push() |
上面的代码唯独没看到 sinon 这个库,说到 ava 是没有 mock 功能的,这就给单元测试的 mock 带来巨大困难,不过我们可以通过引入 sinon 来解决 mock 数据的问题,在 mock 方面上 sinon 做的比 jest 还要优秀,支持沙箱模式,不影响外部数据
给个简单点的例子
<template> <el-card v-for="item in topicList" :key="item.id"> <div class="card-content"> <span class="link" @click="toMember(item.member.username)">{{ item.member.username }}</span> </div> </el-card> </template> <script> export default { props: { topicList: { type: Array, required: true } }, methods: { toMember (name) { this.$router.push(`/member/${name}`) } } } </script> |
对应的测试代码如下
import { shallowMount } from '@vue/test-utils' import test from 'ava' import sinon from 'sinon' test('methods: toMember', t => { const { topicList } = t.context const $router = { push: () => {} } const spy = sinon.spy($router, 'push') const wrapper = shallowMount(TopicListChalk, { propsData: { topicList }, mocks: { $router } }) topicList.forEach((item, index) => { const toMemberText = wrapper.findAll('.card-content').at(index).find('.link') toMemberText.trigger('click') t.true(spy.withArgs(`/member/${item.member.username}`).calledOnce) }) }) |
这里直接将 $router mock 掉,并且使用 sinon.spy 监听执行,至于 this.$router.push 后浏览器有没有跳转并不是单元测试需要关心的,这里的写法也比较特别,test 方法在回调里默认参数为 t,对应的方法都挂载在 t 对象上,上下文可通过 t.context 传递
nuxt 单元测试相关就聊这么多
e2e 测试
这里有个歧义点,nuxt 官网只给出了 e2e 的测试案例 end-to-end-testing
当使用默认脚手架构建的项目,也就是没有 server 端入口文件的项目,这个方案确实可行
但是涉及到其它框架(express|koa)的时候就显得不够用了,很有可能在自定义 server 入口是加入了大量中间件,这对于官网给出的例子是个巨大考验,不可能在每个测试文件里实现一遍 new Nuxt,所以需要更高层的封装,也就是忽略 server 启动流程的差异性,直接在浏览器中抓取页面
react 环境
unit 测试
这一波没得可选,jest 完胜,人家官网就有 React,RN 的支持文档https://jestjs.io/docs/en/tutorial-react.html
文档的案例也是十分全面,没得讲,不赘述
e2e 测试
其实上面讲了两个 e2e 的方案选择,大同小异,需要一个能在 node 跑的无头浏览器,官方没有推荐,这里站 vue 一票选择 nightwatchjs http://nightwatchjs.org/
next 服务端渲染环境
unit 测试
主要讲一下如何配置,先是依赖包
"babel-core", "babel-jest", "enzyme", "enzyme-adapter-react-16", "jest", "react-addons-test-utils", "react-test-renderer" |
在 package.json 里面加 script "test": "NODE_ENV=test jest"
在跟路径下加 jest.config.js
module.exports = { setupFiles: ['<rootDir>/jest.setup.js'], testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'] } |
在跟路径下加 jest.setup.js
import { configure } from 'enzyme' import Adapter from 'enzyme-adapter-react-16' configure({ adapter: new Adapter() }) |
接下来就可以愉快的写测试了
e2e 测试
跳过了~~~
angular 环境
之所以加了这一节,还是因为多少写过一些 angular,angular 作为框架本身就是全面的,cli 新建的项目自身就带有 unit 测试和 e2e 测试
unit 测试默认是 karma + jasmine
e2e 测试默认是 protractor
也没什么可争辩的,这就是官方解决方案,用起来也方便顺手
总结
聊了好多个环境,其实行文目的主要有两方面
测试思想,如何写好单元测试,主要集中在前半文
测试工具推荐和相应配置
测试本身并不复杂,但是想写出高效测试并不容易,千万不要形成为了测试而测试的想法
用谎言去验证谎言得到的还是谎言。。。
大多数情况下都是项目在赶进度没空写测试,抽空把测试补上真的是一件值得去做的事情
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。