前端单元测试,以及给现有的vue项目添加jest + Vue Test Utils的配置
文章原址:https://www.cnblogs.com/yalong/p/11714393.html
背景介绍:
以前写的公共组件,后来需要添加一些功能,添加了好几次,每次修改我都要测试好几遍保证以前的功能不受影响,有次我测试遗漏导致组件出现bug,而且由于是公共组件,我每次修改还得让其他小伙伴更新组件,很是麻烦,所以一定要写测试, 对自己负责,也是对他人负责!
前端测试介绍
1.单元测试(unit测试)
单元测试是把代码看成是一个个的组件,从而实现每一个组件的单独测试,测试内容主要是组件内每一个函数的返回结果是不是和期望值一样。
2.端到端测试(e2e测试)
e2e测试是把我们的程序堪称是一个黑盒子,我不懂你内部是怎么实现的,我只负责打开浏览器,把测试内容在页面上输入一遍,看是不是我想要得到的结果。
两者的存在都是很有意义的:
unit测试是程序员写好自己的逻辑后可以很容易的测试自己的逻辑返回的是不是都正确。
e2e代码是测试所有的需求是不是都可以正确的完成,而且最终要的是在代码重构,js改动很多之后,需要对需求进行测试的时候测试代码是不需要改变的,你也不用担心在重构后不能达到客户的需求。
对于公共组件单元测试就可以满足基本需求了,本文也只讲单元测试。
单元测试的好处
- 减少bug
- 提高代码质量
- 快速定位问题,减少调试时间
- 单元测试还是一份很好的业务文档,每项测试的描述都可以体现业务逻辑
- 降低人工测试的成本,虽然编写及维护测试脚本需要付出额外的成本,但从长远来看,这些成本通常远比采用人工测试要低地多
- 保证该库在后续的开发维护过程中不会出现意料之外的问题;在修改代码「比如优化、重构、修改或添加新的功能等」后,往往需要重新进行测试,这时人工测试通常无法保证覆盖到每一个测试点,这时就会为项目带来隐患
不过不是所有的代码都要写单元测试,因为写单元测试也是有一定工作量的,对于更新频繁,变化较快的需求,让前端写测试,他估计会崩溃。但是对于公共组件,或者其他比较稳定的业务组件,单元测试是很有必要的。
采用 jest + Vue Test Utils进行单元测试的原因
1.Jest是 Facebook 的一套开源的 JavaScript 测试框架, 它自动集成了断言、JSDom、覆盖率报告等开发者所需要的所有测试工具,配置较少,对vue框架友好。
2.Vue Test Utils 是 Vue.js 官方的单元测试实用工具库,为jest和vue提供了一个桥梁,暴露出一些接口,让我们更加方便的通过Jest为Vue应用编写单元测试。
3.vue-cli 默认的单元测试也是使用的这套方案
对于不了解Vue Test Utils 的同学可以先看这里 VueTestUtils, 想了解Jest 的同学可以看这里 Jest
在现有项目中添加(Jest + Vue Test Utils)的测试环境
为了演示配置的过程, 我用vue-cli 初始化了一个简单的项目,webpack 是4.0的
项目代码地址: 点我
1.安装依赖npm i @vue/test-utils babel-jest jest jest-serializer-vue jest-transform-stub vue-jest -D
我的项目安装好如下:
2.修改.babelrc配置
在根目录的.babelrc中添加如下配置
"env": {
"test": {
"presets": ["env"]
}
}
就变成了如下(项目本身的配置不用改)
{
"presets": [
["env", { "modules": false }]
],
"env": {
"test": {
"presets": ["env"]
}
}
}
3.建立测试文件目录
在根目录下建立test目录,test里面再按照如下建立对应文件,文件夹,图上的红字是注释
4.添加jest配置,jest.conf.js内容如下,相关属性的解释也写在了注释里
const path = require('path');
module.exports = {
verbose: true,
testURL: 'http://localhost/',
rootDir: path.resolve(__dirname, '../../'),
moduleFileExtensions: [
'js',
'json',
'vue'
],
moduleNameMapper: {
'^@\/(.*?\.?(js|vue)?|)$': '<rootDir>/src/$1', // @路径转换,例如:@/components/Main.vue -> rootDir/src/components/Main.vue
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir>/test/unit/__mocks__/fileMock.js', // 模拟加载静态文件
'\\.(css|less|scss|sass)$': '<rootDir>/test/unit/__mocks__/styleMock.js' // 模拟加载样式文件
},
testMatch: [ //匹配测试用例的文件
'<rootDir>/test/unit/specs/*.spec.js'
],
transform: {
'^.+\\.js$': '<rootDir>/node_modules/babel-jest',
'.*\\.(vue)$': '<rootDir>/node_modules/vue-jest'
},
testPathIgnorePatterns: [
'<rootDir>/test/e2e'
],
// setupFiles: ['<rootDir>/test/unit/setup'],
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
coverageDirectory: '<rootDir>/test/unit/coverage', // 覆盖率报告的目录
collectCoverageFrom: [ // 测试报告想要覆盖那些文件,目录,前面加!是避开这些文件
// 'src/components/**/*.(js|vue)',
'src/components/*.(vue)',
'!src/main.js',
'!src/router/index.js',
'!**/node_modules/**'
]
}
备注:
单元测试的思想是单纯的测试组件,对于样式,图片等这些静态资源是不予测试的,所以上面的配置中才有了对这些静态资源进行了模拟加载,不然
Jest + Vue Test Util这俩哥们解析不了scss, css, img..这些静态资源,测试就跑不起来了。
同时对于组件内引用的外部资源,也需要模拟,比如axios,下面的测试代码里面有处理的演示。
5.给测试添加eslint配置,test/unit/ 目录下的.eslintrc内容如下
{
"env": {
"jest": true
}
}
6.__mocks__文件目录下建立 fileMock.js,用来处理测试中遇到的静态资源, 内容就一行代码
module.exports = 'test-file-stub';
- 在
specs下写测试用例代码,像下图所示(组件名+spec):
- 在
package.json的scripts里添加测试命令
"unit": "jest --config test/unit/jest.conf.js --coverage"
执行 npm run unit 就可以启动测试了,测试完毕会产生类似下图的报告, 测试覆盖率,测试用例,镜像..都有
编写测试用例
先看下我演示的项目,如下

checkbox 开关控制图片的显隐
表单请求有验证,点击立即创建触发表单验证,验证通过提交表单;点击重置按钮去掉验证提示。
我的组件就两个
一个Form.vue 一个 Main.vue, 就对这俩个组件测试。
测试用例写了三个,如下
里面详细的代码我就不贴出来了,可以去项目源码里面看。
下面说下写这几个测试用例需要注意的地方
1.由于项目用到了element-ui 所以在写测试用例的时候,也需要给模拟的Vue(createLocalVue) install element-ui
关键部分的代码如下:
import { mount, createLocalVue } from '@vue/test-utils'
const localVue = createLocalVue()
import ElementUI from 'element-ui'
localVue.use(ElementUI)
import Form from '@/components/Form'
// 测试表单请求
describe('Test Form Request', () => {
it('Form Request Sucess', () => {
let wrapper = mount(Form, {
stubs: {
transition: false
},
localVue
})
})
})
2.checkbox切换的时候,控制图片显示/隐藏,需要用nextTick
it('show switch img', () => {
wrapper.setData({ switchvalue: true })
// 修改完数据 dom操作没同步 需要用 nextTick
return Vue.nextTick().then(function() {
expect(wrapper.findAll('.logoImg').length).toBe(1)
})
})
3.模拟axios
为什么要模拟axios ?
因为Jest + Vue Test Utils这套环境中是没有
axios的,所以他不认axios, 但是组件代码里面确实调用了axios, 那么我们就需要模拟一个axios出来
新建 axios.js 文件
axios.js 的内容如下:
module.exports = {
get: jest.fn(() => Promise.resolve({ status: 200 }))
}
我这里只用到了 status: 200,大家根据自己需求设置返回的数据。
测试用例代码如下:
import { mount, createLocalVue } from '@vue/test-utils'
import Vue from 'vue'
const localVue = createLocalVue()
import ElementUI from 'element-ui'
localVue.use(ElementUI)
import axios from 'axios'
import Form from '@/components/Form'
// 测试表单请求
describe('Test Form Request', () => {
it('Form Request Sucess', () => {
let wrapper = mount(Form, {
stubs: {
transition: false
},
localVue,
propsData: {
initFormData: {
name: '一起团建',
type: ['地推活动'],
desc: '吃喝玩乐'
}
}
})
wrapper.find('.confirm').trigger('click')
return Vue.nextTick().then(function() {
expect(wrapper.vm.sucess).toBe(true)
let url = 'http://rap2api.taobao.org/app/mock/233956/tbl-unit-test?name=' + wrapper.vm.ruleForm.name + '&nature=' + wrapper.vm.ruleForm.type.join(',') + '&form=' + wrapper.vm.ruleForm.form
expect(axios.get).toBeCalledWith(url)
})
})
})
以上介绍了单元测试,以及如何在现有项目基础上添加测试的配置,并写了几个测试用例,应该可以让不了解单元测试的同学入门了,更高级点的可以看 这里 这个项目里面的单元测试就比较全面,大家可以参考下。
演示项目代码: https://github.com/YalongYan/vue-test-utils-jest
参考连接:
Vue Test Utils
Jest Using With Wbpack
使用jest对vue项目进行单元测试
ui组件如何进行单元测试
Jest Mock
用Jest测试Vue中的Methods中的方法和Mock依赖
前端单元测试,以及给现有的vue项目添加jest + Vue Test Utils的配置的更多相关文章
- 如何为你的 Vue 项目添加配置 Stylelint
如何为你的 Vue 项目添加配置 Stylelint 现在已经是 9102 年了,网上许多教程和分享帖都已经过期,照着他们的步骤来会踩一些坑,如 stylelint-processor-html 已经 ...
- Vue项目添加动态浏览器头部title
0. 直接上 预览链接 + 效果图 Vue项目添加动态浏览器头部title 1. 实现思路 ( 1 ) 从路由router里面得到组件的title ( 2 ) title存vuex (本项目已经封装h ...
- 为 VUE 项目添加 PWA 解决发布后刷新报错问题
为什么要给 VUE 项目添加 PWA 为什么要添加?因为不管是部署在 IIS,还是 nginx,每次应用部署后,再次访问因为旧的 js 已经不存在,所以页面访问的时候会整个报错,报错的结果就是一个白屏 ...
- Vue项目无法使用局域网IP直接访问的配置方法
一般使用 vue-cli 下来的项目是可以直接访问局域网 IP 打开的,比如 192.168.1.11:8080 .但是最近公司的一个项目只可以通过 localhost 访问. 需要配置一下,才可直接 ...
- Vue 项目添加单元测试发现的问题及解决
用 Jest 测试单文件组件 1.安装 Jest 和 Vue Test Utils npm install --save-dev jest @vue/test-utils 2.配置 package.j ...
- GitHub Vue项目推荐|Vue+Element实现的电商后台管理系统功能丰富
GitHub Vue项目推荐|mall-admin-web是一个电商后台管理系统的前端项目基于Vue+Element实现 主要包括商品管理.订单管理.会员管理.促销管理.运营管理.内容管理.统计报表. ...
- 搭建vue项目并启动vue项目
链接地址:https://blog.csdn.net/aa792978017/article/details/82939483 Vue.js是现在比较优秀的Web前端框架,下面开始从零开始搭建一个Vu ...
- 简单vue项目脚手架(vue+webpack2.0+vuex+vue-router)
github地址 使用技术栈 webpack(^2.6.1) webpack-dev-server(^2.4.5) vue(^2.3.3) vuex(^2.3.1) vue-router(^2.5.3 ...
- pycharm中新建Vue项目时没有vue.js的解决办法
可能很多小伙伴在使用pycharm 1,新建vue项目的时候并没有发现vue.js的名字, 2,新建.vue文件(即单文件组件)的时候没有 下面就来帮助大家一下,仅供参考 如图: 1.首先我们打开设置 ...
随机推荐
- Prometheus 监控 Redis 集群的正确姿势
Prometheus 监控Redis的正确姿势(redis集群) Prometheus 监控 Redis cluster,其实套路都是一样的,使用 exporter. exporter 负责采集指标, ...
- iTerm2快速SSH连接并保存密码
背景 Mac自带terminal,以及比较好用的iTerm2命令行工具,都缺乏一个功能,就是远程SSH连接,无法保存密码.一种方法是将本机的ssh_key放到远程服务器中实现无密码登录.这种方法在很多 ...
- java 中操作字符串都有哪些类?(未完成)它们之间有什么区别?(未完成)
java 中操作字符串都有哪些类?(未完成)它们之间有什么区别?(未完成)
- Event Binding in Angular
https://www.pluralsight.com/guides/angular-event-binding Introduction In this guide, we will explore ...
- 解决安卓app在真机上的无法登录问题
和小伙伴用安卓做的app在模拟器上可以正常使用,但是变成apk发到手机上下载使用时,出现无法的登录问题,而且登录提示的错误出现一秒就消失了,无法看清. 于是找了一下老师帮忙,老师是通过在电脑主机上插入 ...
- 端口与服务-ftp服务
端口与服务-ftp服务 1概述 1.1.从先知和乌云上爬取端口历史漏洞报告,总结报告 1.2.全面总结,出具一个表格之类的汇总表 2.ftp # -*- coding: utf-8 -*- impor ...
- BZOJ 1022 / P4279 Luogu [SHOI2008]小约翰的游戏 (反Nim游戏) (Anti-SG)
题意 反Nim游戏,两人轮流选一堆石子拿,拿到最后一个的输.问先手是否必胜. 分析 怎么说,分类讨论? 情形1:首先考虑最简单的情况,所有石子数都为1.那么奇数堆石子为必败,偶数为必胜 情形2:然后考 ...
- Luogu P1092 虫食算 爆搜
心路历程:震惊,我竟然得了$90$分!!...康康数据...奥..(忽然有了邪恶的卡数据的想法) 于是把$for(int \space i=0;i<n;++i)$改成了$for(int \spa ...
- Java进阶知识14 Struts2中的S标签
1.A 开头 <s:a href=""></s:a> //超链接,类似于html里的<a></a> <s:action nam ...
- [CTS2019]田野(80分)
loj嘟嘟嘟 学完模拟退火后开始搞这道题,搞了一下午最终搞到了80分,剩下的实在不知道怎么办了-- 首先肯定是把有交点的线段划分到一个集合,然后对每一个集合求一遍凸包. 然后两两合并,如果新的凸包的周 ...