单元测试学习记录
开头狗头警告~哈哈
目前自己所在公司规模不大,还是外包性质的,所以项目众多,每天都疲于业务之间,最近忙里偷闲,觉得咱们做技术的虽然是服务于业务,但是也不能一直被业务支配,还是不能忘记提升自己的技术,自身技术才是核心竞争力。很多新技术,可能在一些小项目上用不到,甚至在一些新技术的使用方面,很多人会有很多顾虑,但是我始终觉得,技术没有高低贵贱,如果有,那肯定是使用者的问题。哈哈哈,逼逼赖赖了这么多,咱们进入正题吧
单元测试概念
对最小的可测试单元进行自动化测试 ---(个人理解就是对方法进行测试)
- 分模块开发,方便地定位到那个单元出来问题
- 保证代码质量
- 驱动开发
第一点和第二点都比较好理解,讲到第三点,就需要讲两个概念了:TDD 和 BDD
TDD
- 需求分析 --> 编写单元测试 --> 编写代码使单元测试通过 -->重构
BDD
- 从业务角度定义目标 --> 找到实现目标的方法 --> 编写单元测试 --> 实现行为 --> 检查产品
单元测试的原则
- 及时修改和维护
- Code review
- 只测单一的点
- 尽量贴近真实
- 避免测试中逻辑过于复杂
现状
比如我公司现在的开发流程就是以 BDD 开发流程为主,先需求分析,然后编写技术实现文档,审核完后 开发er 开始开发需求,测试er 开始写自己的测试用例(两边并发执行),开发完成之后,开始进行测试。这样的过程符合一般人们的逻辑,但是看了 TDD 之后,有一种耳目一新的感觉,隐约觉得 TDD 更为合理。(但是想要走TDD流程,那针对公司现有开发流程需要改进的地方就太多了,慢慢来吧)
使用工具
测试框架
- Jest - 基于 jasmine,对react友好。是facebook推出的一款测试框架,集成了 Mocha,chai,jsdom,sinon等功能
- Jasmine - BDD 风格,自带assert 和 mock
- Mocha - 全面审核node和浏览器两个端
- Qunit - 出资 JQ
断言库
- Chai - 支持所有风格、全面
- Should
- export
- Assert - node环境直接使用
Mock库(主要写一些间谍函数或者屏蔽函数)
- sinon
Test runner 库
- Karma
覆盖率工具
- istambul(伊斯坦布尔,哈哈哈)
准备上手啦!
上手前,先介绍一下大致情况
咱是用vue项目做demo的,但这个应该不影响哈。首次使用的话,我们用了 Mocha + Karma + sinon + chai
新建test-demo项目
这里使用的是 vue-cli2,直接上图
这边选择Karma and Mocha生成项目,打开文件
test 目录下有unit文件夹
这是Karama配置文件
接着我们打开specs文件,里面有一个HelloWorld.spec.js文件,改文件就是接下来,我们要写测试用例的地方编写第一个测试用例
- 在 helloworld组件中写一个方法
m1 (a, b) {
return a + b
}
- 在HelloWorld.spec.js中写一个测试用例
import Vue from 'vue'
import HelloWorld from '@/components/HelloWorld'
//所有的测试用例都下载describe中
describe('HelloWorld.vue', () => {
//导入要测试的组件
const Constructor = Vue.extend(HelloWorld)
//获取该组件的 this
const vm = new Constructor().$mount()
//开始一个测试用例
it('should render correct contents', () => {
expect(vm.$el.querySelector('.hello h1').textContent)
.to.equal('Welcome to Your Vue.js App')
})
it('is m1 add two arguments', () => {
//获取m1方法
const m1 = vm.m1
//使用断言库,(期待m1(1,2)等于3,纯属字面意思,哈哈哈)
expect(m1(1, 2)).to.equal(3)
})
})
- 控制台运行单元测试
npm run unit
OK,第一个测试用例编写成功,测试通过!
第一个异步单元测试
- 在HelloWorld.vue写一个异步函数
async m4 (cb) {
await axios.get('http://www.xxx.com')
let data = cb()
return data
}
- 在HelloWorld.spec.js写一个获取axios被调用次数的测试用例,使用sinon
注意,一定要引入promise,否则会报错
import Vue from 'vue'
import HelloWorld from '@/components/HelloWorld'
import axios from 'axios'
import Promise from 'es6-promise'
Promise.polyfill()
describe('HelloWorld.vue', () => {
const Constructor = Vue.extend(HelloWorld)
const vm = new Constructor().$mount()
it('should render correct contents', () => {
expect(vm.$el.querySelector('.hello h1').textContent).to.equal('Welcome to Your Vue.js App')
})
it('is m1 add two arguments', () => {
const m1 = vm.m1
expect(m1(1, 2)).to.equal(3)
})
it('接口被请求', () => {
// spy,stub,MOCK
// spy是可以获取到对应函数的调用信息,但是不能屏蔽
// stub会拦截掉这个方法
const m4 = vm.m4
// 间谍函数
let axiosspy = sinon.spy(axios, 'get')
m4(axiosspy)
// 获取axios被调用次数
console.log(axiosspy.callCount)
axiosspy.restore()
})
})
- 控制台运行单元测试
npm run unit
成功打印接口请求次数,但是请注意,spy不能屏蔽该请求,接下来,我们实现接口屏蔽
编写一个屏蔽接口的测试用例
- 在HelloWorld.vue写一个异步函数
async m5 (cb) {
await axios.get('http://www.baidu.com')
let data = cb()
return data
}
- 在HelloWorld.spec.js写一个屏蔽axios调用的测试用例
it('接口被屏蔽', async () => {
// spy,stub,MOCK
// spy是可以获取到对应函数的调用信息,但是不能屏蔽
// stub会拦截掉这个方法
let m5 = vm.m5
let callback = sinon.stub(axios, 'get')
let axiosspy = sinon.spy(() => {
return 4
})
expect(await m5(axiosspy)).to.equal(4)
callback.restore()
})
- 控制台运行单元测试
npm run unit
OK,通过了单元测试
总结
这是第一次尝试单元测试,还是有很多概念性的知识不太懂,但是对于单元测试的话大致也算了解了一下,后面自己有尝试了使用 JEST进行单元测试,大体差不多,语法也很相似,只是JEST有个坑:在jest.conf.js文件中,要把 mapCoverage: true 这一行注释,并且加上
verbose: true,
testURL: 'http://localhost/'
才能正常运行测试环境。
呼,写文章不易,掘友看了,若是觉得有什么不妥的,请留言哦,感谢了,点赞我就不奢求了,只是个学习记录,不喜勿喷哦~