一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第20天,点击查看活动详情。
前情提要
单元测试这个东西既陌生又熟悉。陌生是因为国内高速迭代的过程让项目开发中根本不允许它的存在。熟悉是因为这个东西被大多数人认为是在开发环节中应该存在的,而且是有利的。
为什么要单元测试
-
背景: 稍微好一点的公司和项目都有单元测试
-
可测试判定:1最小的,2可测试 ,3可执行 进行测试 基本上都是测一个方法,当然现在组件化。
-
单元测试开发的流程
- 没有单元测试
- 原型图 -> 开发 -> 项目写完 -> 点点点测试
- 有单元测试
- 原型图 ->需求 -> 分析需求 -> 得出要实现这个需求,要写那些基本功能 -> 编写单元测试 -> 开始写代码 -> 跑之前写好的单元测试 -> 代码没问题 -> 可以提交了
- 没有单元测试
-
好处
- bug发现=》越早发现越好
- 多人得开发的环境,多人合作=》每天产出=》集成到一起
- 整个软件开发追求的趋势,追求自动化,工程化
单元测试怎么去做
单元测试包括五个部分
1.测试框架(jest /Mocha )
jest :直接npm安装,不用去配置 jest test.js 他已经集成好了断言库,Mock库,Test runner,覆盖率工具(大部分项目都是用jest)
Mocha :需要自己去配置 断言库,Mock库,Test runner,覆盖率工具这些都需要自己去配置
2.断言库
function add(num1,num2){
return num1+num2
}
也有比较特殊的,比如a方法中调用了b方法
function a(){
// 这里要忽略调b方法的真实调用,模拟一个返回值,这样子做到了只测a方法调用,不被b影响
let result = b()
return result
}
3.Mock库
sinio框架: 这个和Mock.js 有本质的区别
4.Test runner (karma框架)
需要执行环境去跑代码,这里我们肯定不能用浏览器去跑单元测试,因为每次写完一个方法,不能每次去打开浏览器。 我们可以用node环境,但是node环境始终和浏览器有差别 所以可以用一个工具,提供一个模拟浏览器,不用打开浏览器跑起来
5.覆盖率工具(istanbul)
行覆盖率:可执行语句比例 函数覆盖率:函数被覆盖的比率 分支覆盖率:判断语句分支执行比例 比如只测了if里面的内容,没有测else里面的逻辑 真实代码里面很难出现百分之百的覆盖率,一般百分之七八十就够了
jest实践
- 测试用例: 分析需求要写那些方法,针对写出单元测试
- 测试套件: 一系列的,比如针对这个组件里的很多单元测试,集合在一起,一个测试套件,可以包含很多单元测试
- 一般在项目本地和全局都安装
- 一般情况下,要测的代码一个文件,单元测试一个文件
function a(num1,num2){
return num1+num2
}
// 异步方法
function a(num1,num2,cb){
setTimeout(()=>{
return num1+num2
},1000)
}
// 依赖外部方法 先屏蔽掉真正调用,再模拟返回值
function c(){
var result =model.f1()
return ++result
}
describe('test a.js',()=>{ // describe 测试套件 test a.js 套件描述
it('a should add two argument',()=>{
expect(a(1,2)).toEqual(3)
}} // it 测试用例
it('b should add two argument',(done)=>{
function callback(result){
expect(b(1,2)).toEqual(3)
done()
}
b(1,2,callback)
}} // it 测试用例
it('c',()=>{
var flmock = model.f1.mockRurnValue(2)
expect(c()).toEqual(3)
}}
})
现在的开发中,更多的是测组件,比如vue项目中,测的是vue组件,vue的文件。每个组件是一个测试套件
用过vue-cli就知道,使用脚手架,他的模板选择要单元测试就可以了,完成后就会多一个tests文件夹
命名规则 测HelloWord组件 ,那么单元测试的名称 是HelloWord .spec.js
当然不强制,一般是按照这个规则来
vue的单元测试,百分之八十的测试,都是直接测渲染结果
import HelloWord from HelloWord.spec.js
// import过来的只能是选项配置,而不是实例,在monted才有实例
mount(HelloWord) // mount是Vue提供给单元测试使用的工具
import axios from 'axios'
// 在测试之前,要屏蔽掉请求,m模拟返回值
describe('HelloWord',()=>{
it('render right'),()=>{
jest.mock('axios')
jest.spyOn(axios,'get').mockResolveValue({
data:[{content:"this is 1"},{content:"this is 2"},{content:"this is 3"},]
})
const helloword = mount(HelloWord)
// vue 渲染是异步的
setTimeOut(()=>{
expect(helloword.html()).toContain('this is 1')
expect(helloword.html()).toContain('this is 2')
expect(helloword.html()).toContain('this is 3')
})
}
})