大厂视野
1.流量大
- 性能优化
2.项目复杂
- 源码
3.持续迭代
4.项目稳定运行
- 自动化测试
- 需求评审
- 开发
- 测试(人点)(可以使用自动化测试完成一部分)
- 上线
5.为什么要写测试呢
- 测试代码可读性好,易于维护
- 替代了测试的部分工作,无形中完成了一部分任务
准备
1.了解自动化测试
2.jest
3.cypress
4.端对端和自动化
测试分类
常⻅见的开发流程⾥里里,都有测试⼈人员,这种我们成为⿊黑盒测试,
测试⼈人员不不管内部实现机制,只看最外层的输⼊入输出,⽐比如你写⼀一个加法的⻚页⾯面,会设计 N个case,测试加法的正确性,这种代码⾥里里,我们称之为E2E测试
更更负责⼀一些的,我们称之为集成测试,就是集合多个测试过的单元⼀一起测试
还有⼀一种测试叫做⽩白盒测试,我们针对⼀一些内部机制的核⼼心逻辑 使⽤用代码 进⾏行行编写 我们称之为单元测试
这仨都是我们前端开发⼈人员进阶必备的技能!
我们其实⽇日常使⽤用 console,算是测试的雏形吧,console.log(add(1,2) == 3)
测试的好处
组件的单元测试有很多好处:
- 提供描述组件⾏行行为的⽂文档
- 节省⼿手动测试的时间
- 减少研发新特性时产⽣生的 bug
- 改进设计
- 促进重构
⾃自动化测试使得⼤大团队中的开发者可以维护复杂的基础代码。让你改代码不不再⼩小⼼心翼翼
我们先来创建一个vue项目
装好了以后有个test目录,下有两个目录,unit和e2e,unit是单测,e2e是端对端
npm run test:unit 就可以进行测试了
单元测试
单元测试(unit testing),是指对软件中的最⼩小可测试单元进⾏行行检查和验证。例如一个函数。
单测针对组件 或者函数 或者模块(开发人员知道具体逻辑)
在vue中,推荐⽤用 Mocha+chai 或者jest,咱们使⽤用 jest演示,语法基本⼀一致
😊写一个demo
在src建立utils.js,写个add函数导出
export function add(x,y) { return x + y }
在tests下的unit下的example.spec.js中修改(当然也可以新建一个*.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) // }) // }) import { add } from '@/utils.js' describe('测试加法函数',()=>{ //测试代码可读性最好 //分组 it('一个具体的功能测试,测测试数字相加',()=>{ expect( add(1,2) ).toBe(3) }) it('一个具体的功能测试,测测试数字和字符串相加',()=>{ expect( add('a',2) ).toBe('a2') }) it('一个具体的功能测试,测测试数字字符串相加',()=>{ expect( add('1',2) ).toBe(3) }) })
npm run test:unit 后
这个案例我们就用到了4个api
api介绍
- describe : 定义⼀一个测试套件
- it :定义⼀一个测试⽤用例例
- expect :断⾔言的判断条件
- toBe :断⾔言的⽐比较结果
测试vue组件
components下新建KaiKeBa.vue
<template> <div> <span>{{ msg }}</span> <span>{{ msg1 }}</span> <button class="btn" @click="changeMsg">点我</button> </div> </template> <script> export default { data(){ return { msg: "vue test", msg1: '你好' } }, created() { this.msg = 'aftermounted' }, mounted() { this.msg1 = '开课吧' }, methods: { changeMsg(){ this.msg = 'click over' } }, } </script>
views目录下的home组件中引入
<template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> <KaiKeBa></KaiKeBa> </div> </template> <script> // @ is an alias to /src import HelloWorld from '@/components/HelloWorld.vue' import KaiKeBa from '@/components/KaiKeBa.vue' export default { name: 'home', components: { KaiKeBa, HelloWorld } } </script>
在tests目录下的unit目录下建立kaikeba.spec.js
import Vue from 'vue' import KaiKeBaComp from '@/components/KaiKeBa.vue' import { mount } from '@vue/test-utils' describe('测试KaiKeBa组件',() => { it('测试初始化的data',() => { expect( KaiKeBaComp.data().msg ).toBe('vue test') }) //created和mounted里数据测试都是一样的 it('测试新建完毕后,create生命周期后的数据',() => {//created let vm = new Vue(KaiKeBaComp).$mount() expect(vm.msg).toBe('aftermounted') }) it('测试新建完毕后,create生命周期后的数据',() => {//mounted let vm = new Vue(KaiKeBaComp).$mount() expect(vm.msg1).toBe('开课吧') }) //点击事件测试 it('测试点击后,msg的改变',() => { // $mount处理不了用户交互,所以我们要用到vue官方推荐的@vue/test-utils let wrapper = mount(KaiKeBaComp) expect( wrapper.vm.msg ).toBe('aftermounted') //点击一下 wrapper.find('.btn').trigger('click') expect( wrapper.vm.msg ).toBe('click over') }) })
如果测试用户交互的话,需要用到官方推荐的@vue/test-utils,执行cnpm i @vue/test-utils --save,相关文档在vue官网
在 @vue/test-utils 中引入mount替代vue的$mount的是因为$mount的是虚拟的,存在虚拟内存中,处理不了dom,所以用mount(对不对我不知道,这句话仅供参考)
测试覆盖率
jest⾃自带覆盖率,如果⽤用的 mocha,需要使⽤用 istanbul来统计覆盖率
package.json⾥里里修改 jest配置
jest: { "collectCoverage": true, "collectCoverageFrom": ["src/**/*.{js,vue}"], }
倘若有个jest.config.js那么就在 moduleFileExtensions 上一行加入,这个文件是对jest的配置
"collectCoverage": true, "collectCoverageFrom": ["src/**/*.{js,vue}"],
在跑一下npm run test:unit
生成的报告文件在coverage目录下,打开可以看到这么个鬼东西
这个测试报告可以很精确的看到我们哪些没测试,哪些测试了,我在KaiKeBa里加点东西不测试,来看看结果
蓝色的我们可以点进去的
指出了没有测到的地方,判断了newData是否等于1,显然不等于的
我们可以给他测试下,要这么写,给newData赋值
it('测试点击后,newData == "1"的结果',() => { // $mount处理不了用户交互,所以我们要用到vue官方推荐的@vue/test-utils let wrapper = mount(KaiKeBaComp) wrapper.vm.newData = '1' //点击一下 wrapper.find('.btn').trigger('click') expect( wrapper.vm.msg ).toBe('click false') })
如何测试不通过就阻止代码git提交
安装husky:cnpm i husky --save
配置husky,在package.json
"husky": { "hooks": { "pre-commit": "npm test", "pre-push": "npm test", "...": "..." } }
当然这是文档的,我们要按我们所需的改成
"husky": { "hooks": { "pre-commit": "npm run test:unit" } }
代表再提交(commit)前先执行npm run test:unit
🐱🚀验证:
修改测试代码文件kaikeba.spec.js
由
it('测试新建完毕后,create生命周期后的数据',() => {//created let vm = new Vue(KaiKeBaComp).$mount() expect(vm.msg).toBe('aftermounted') })
改为
it('测试新建完毕后,create生命周期后的数据',() => {//created let vm = new Vue(KaiKeBaComp).$mount() expect(vm.msg).toBe('aftermounted1') })
这样测试肯定是不通过的
这时,我们来提交代码,add后再commit
那么我们再将测试文件改回来,让测试可以通过
如图:测试通过,代码也commit提交了
E2E测试
e2e针对应用,站在测试人员的角度,没有什么mount 加载,只有按钮 页面,输入框,文本等
借⽤浏览器器的能力,站在⽤户测试⼈员的角度,输⼊框,点击按钮等,完全模拟用户,这个和具体的框架关系不大,完全模拟浏览器行为
😒将views下的Home组件的
<HelloWorld msg="Welcome to Your Vue.js App"></HelloWorld>
代码恢复
😒看看tests目录下e2e目录下的spec下的test.js,有这么一段
// https://docs.cypress.io/api/introduction/api.html describe('My First Test', () => { it('Visits the app root url', () => { cy.visit('/') cy.contains('h1', 'Welcome to Your Vue.js App') }) })
这是测试代码,如果我们不做前面的恢复操作的话,测试肯定是不通过的
😒执行npm run test:e2e,进行测试
项目会启动,并且会弹出一个有ok的弹窗,我们直接确定,还会有测试文件的js,选择对应的测试文件点进去
这样就已经测试通过了
😒再来测试一个about页
// https://docs.cypress.io/api/introduction/api.html describe('My First Test', () => { it('Visits the app root url', () => { //访问根目录 cy.visit('/') cy.contains('h1', 'Welcome to Your Vue.js App') }) it('测试about页', () => { //访问about cy.visit('about') cy.contains('h1', 'This is an about page') }) })
结果是这个样子
后测的about,就最后打开了about页,也停留在了about页面
这些都是页面某个元素的文本的测试,那么我们再来个交互试试,在我们的KaiKeBa组件上有个点击事件,我们来试试
// https://docs.cypress.io/api/introduction/api.html describe('My First Test', () => { it('Visits the app root url', () => { //访问根目录 cy.visit('/') cy.contains('h1', 'Welcome to Your Vue.js App') }) it('测试about页', () => { //访问about cy.visit('about') cy.contains('h1', 'This is an about page') }) it('KaiKeBa组件',() => { //访问根目录 cy.visit('/') cy.contains('#msg','aftermounted') cy.get('button').click()//点击button元素 cy.contains('#msg','click over') }) })
左边那一条条可以点击,点击不同的项,也会进入不同的事件状态,例如我点了CONTAINS,文本变成了click over
题外话:测试页面前后差异,或者两个页面的差异可以用page-monitor;地址: https://github.com/fouber/page-monitor
如何测试node?
来源:https://blog.csdn.net/qq_32442973/article/details/100827516