24-单元测试如何做
24-单元测试如何做¶
统计信息:字数 4250 阅读9分钟
软件开发过程中需要测试:白盒测试(单元测试)和黑盒测试(点击界面功能)
- 什么是单元测试
- 单元测试常用的库
- VUE中如何使用单元测试
单元测试概念¶
概念¶
工程化:为了应付工程体系的不断复杂化,增加一些工具让我们更方便工作
前端工程化:webpack + git + 单元测试(使用软件工程的方法处理前端)
单元测试:对软件中最小的可测试单元进行测试。
单元测试的目的:团队分模块开发(前后端分离),方便定位模块出现问题;保证了代码的质量;测试驱动开发。
单元测试的两种类型:TDD(测试驱动开发)BDD(行为驱动开发)
TDD: 从需求角度看,用户需要什么,如果不是就是代码错误(用户需求分析-编写单元测试-编写代码并通过单元测试-代码重构)
BDD:行为驱动开发:从具体的功能角度出发,结果应该是什么。(从产品角度定义目标-找到目标实现的方法-编写单元测试-实现行为-检查产品)
Mock库作用:如果一个方法中使用另一个方法,可以使用Mock库屏蔽另一个方法带来的影响。
测试用例:测试输入+执行+预期输出结果
测试原则:测试案例需要及时维护修复(测试和代码同步修改)code review:确保代码功能正常;代码符合项目规范
单元测试使用哪些库¶
单元测试范围¶
测试框架+断言库+Mock库+test runner+覆盖率工具
测试框架¶
Jest 集成了断言库和Mock,基于jasmine,对React友好
Jasmine bdd风格,包含 assert + Mock
Mocha需要自己去配置断言库和Mock(适合node和浏览器)
断言库:chai (全面)、should、expect、Assert (node)
Mock库:sinons
TestRunner:karma
覆盖率工具:istanbul
框架中使用单元测试¶
phantomJS 无头浏览器:不属于任何浏览器的特点,遵循前端的测试规范(主要用于测试)
React 通常使用 Jest 做单元测试;VUE在初始化使用 vue-cli 可以
可以选择Jest,可以选择mocha+chai+sinon自己配置
function a() {
b();
}
function b() {
}
测试需要增加配置文件
karma.conf.js
module.exports = function karmaConfig(config) {
config.set({
browser: ['PhantomJS'],
frameworks: ['mocha', 'sinon-chai'],
reporters: ['spec', 'coverage'],
files: ['./index.js'],
preprocessors: {
'./index.js': ['webpack', 'sourcemap']
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true
},
});
}
webpack.test.config.js
index.js 是框架默认提供的
Package.json
{
"scripts": {
"test": "npm run unit",
"unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
}
}
例子¶
helloworld.spec.js
import Vue from 'vue';
import HelloWorld from '@/components/HelloWorld';
import Promise from 'es6-promise';
Promise.polyfill();
describe('Hello.vue', () => {
it('should render correct contents', () => {
const Constructor = Vue.extend(HelloWorld);
// 组件构造类
const vm = new Constructor().$mount();
expect(vm.$el.querySelector('.hello h1').textContent).to.equal('Welcome to my Vue.js App');
});
// 测试方法(异步的方法如何测试)
it('test function m1', () => {
const m1 = vm.m1;
expect(m1(2, 3)).to.equal(5);
});
it('async m2 should return 3', () => {
const m2 = vm.m2;
m2(1, 2, data => {
expect(data).to.equal(3);
});
m2(1, 2).then((res) => {
expect(data).to.equal(3);
});
});
// getmes
it('接口被请求', () => {
// spy stub
let axiosspy = sinon.spy(axios, 'get');
console.log(axiosspy.callCount);
let callback = sinon.spy(() => {
return 5;
});
const getmes = vm.getmes;
expect(getmes(callback)).to.equal(4);
});
});
// 原组件
methods: {
m1: function(a, b) {
return a + b;
},
m2: function(a, b, fn) {
setTimeout(() => {
fn(a + b);
}, 1000);
},
getmes: function(fn) {
axios.get('www.baidu.com');
let res = fn();
this.data = res;
return data;
}
}