浅析前端vue项目使用单元测试框架一

测试库:https://www.awesomes.cn/repos/Applications/Testings

应用组件功能测试

组件测试vue-TDD的开发流程 (TDD什么意思?下面有介绍)
{
1.编写组件测试-在单元测试中将设计组件的名称、属性接口、事件接口、用断言工具确定衡量这个组件正确的标准
2.编写组件代码-以单元测试为引导程序,编写组件真实的实现代码,让测试通过
3.运行测试,并看到测试通过
4.重构
}

测试工具:

测试管理工具(测试加载器) Karma

{
Karma-自动化测试程序的入口,执行以下任务
1.为测试程序注入指定依赖包
2.可同时在一个或多个浏览器宿主中执行测试,满足兼容性测试需求
3.执行代码覆盖性测试
4.输出测试报告
5.执行自动化测试
}

测试框架 Mocha (测试Node和浏览器js代码)
vue官网单元测试框架 Vue Test Utils

断言库 chai / sinon

{
expect和should是BDD风格,使用相同链式语言组织断言,不同点在于初始化断言方式:
1.expect使用构造函数来创建断言对象实例
2.should通过为Object.prototype新增方法来实现断言(should不支持IE); expect直接指向chai.expect
而should则是chai.should()


注:在构建vue-cli工程时,添加了单元测试是不需要手动配置chai;
chai和sinon 被Karma通过Karma-sinon-chai插件直接嵌入到单元测试的上下文中,不用import就可以使用
}

那问题来了?sinon是什么?辅助库 sinon-chai
{
sinon: 负责仿真
三个方法: 调用侦测Spy / 接口仿真 Stub / 对象仿真 Mock
}


测试浏览器 chrome (PhantomJs 无界面浏览器,速度比chrome快)

测试覆盖率统计工具 Karma-coverage


test文件夹下unit,单元测试相关文件


specs-中存放测试脚本(所有的测试文件, 都将放specs这个目录下, 并以测试脚本名.spec.js结尾命名)
coverage文件里存放测试报告,html打开的是代码覆盖率
Karma.config.js配置文件


npm run unit 输出

demo:

1.被测试的组件HelloWorld.vue

<template>
<div class="hello">
<h1>Welcome to Your Vue.js App</h1>
</div>
</template>


2.测试脚本HelloWorld.spec.js

import HelloWorld from '@/components/HelloWorld';
import { mount, createLocalVue, shallowMount } from '@vue/test-utils'

describe('HelloWorld.vue', () => {
it('should render correct contents', () => {
const wrapper = shallowMount(HelloWorld);
let content = wrapper.vm.$el.querySelector('.hello h1').textContent;
expect(content).to.equal('Welcome to Your Vue.js App');
});
});

describe是"测试套件",表示一组相关的测试。它是一个函数,
第一个参数是测试套件的名称("加法函数的测试"),
第二个参数是一个实际执行的函数。

it是"测试用例"(test case),表示一个单独的测试,是测试的最小单位。
它也是一个函数,第一个参数是测试用例的名称,第二个参数是一个实际执行的函数。
所有的测试用例(it块)都应该含有一句或多句的断言

断言(判断源码的实际执行结果与预期结果是否一致),如果不一致, 就会抛出错误
expect(content).to.equal('Welcome to Your Vue.js App')实际为变量content应等于'Welcome to Your Vue.js App'
Vue的脚手架提供的断言库是sino-chai, 是一个基于Chai的断言库

chai官方文档:https://www.chaijs.com/
chai官方文档翻译:https://www.jianshu.com/p/f200a75a15d2


注意:Mocha测试钩子

在describe块中提供了四个钩子: before(), after(), beforeEach(), afterEach(). 它们会在以下时间执行:

describe('钩子说明', function() { // 第一个参数提示要测试什么;第二个匿名函数

before(function() {
// 在所有场景执行之前执行(执行一次)
});

after(function() {
// 在所有场景执行之后执行(执行一次)
});

beforeEach(function() {
// 在每个场景测试执行之前执行
});

afterEach(function() {
// 在每个场景执行完成之后执行
});

});

举个例子:
describe('Array', () => {
let expectTarget = []

beforeEach(() => {
// 在每个场景测试执行之前执行
expectTarget.push(1)
});

afterEach(() => {
// 在每个场景执行完成之后执行
expectTarget = [] // 清空
});

it('应该存在一个为1的整数', () => {
expect(expectTarget[0]).to.eqls(1)
});

it('应该存在多个的期望值检测', () => {
expect(expectTarget[0]).to.eqls(1)
expect(true).to.eqls(true)
});
});

Mocha 官方文档:https://mochajs.org/
Mocha 官方文档翻译:https://www.jianshu.com/p/9c78548caffa
阮一峰 - 测试框架 Mocha 实例教程:http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html

vue-test-utils官方文档:https://vue-test-utils.vuejs.org/zh/api/#render
vue-test-utils常用api

find(): 返回匹配选择器的第一个DOM节点或Vue组件的wrapper, 可以使用任何有效的选择器
text(): 返回wrapper的文本内容
html(): 返回wrapper DOM的HTML字符串
trigger(): 在该 wrapper DOM 节点上触发一个事件
setData(): 设置data的属性并强制更新
it('find()/text()/html()方法', () => {
const wrapper = mount(Counter);
const h3 = wrapper.find('h3');
expect(h3.text()).to.equal('Counter.vue');
expect(h3.html()).to.equal('<h3>Counter.vue</h3>');
})

it('trigger()方法', () => {
const wrapper = mount(Counter);
const buttonOfSync = wrapper.find('.sync-button');
buttonOfSync.trigger('click');
buttonOfSync.trigger('click');
const count = Number(wrapper.find('.num').text());
expect(count).to.equal(2);
})

it('setData()方法',() => {
const wrapper = mount(Counter);
wrapper.setData({foo: 'bar'});
expect(wrapper.vm.foo).to.equal('bar');
})


遇到vue-异步测试情况

Mocha异步测试在it内加一个done函数,在所有的断言执行完成后调用done()就可以释放测试用例并告知Mocha测试的执行结果

例子:一个User对象,具有一个save方法,这个方法通过ajax将数据保存到服务器端,若服务端没有返回错误,即认为这个save方法是成功的

describe('User', () => {
describe('#save()方法', () => {
it('应该成功保存到服务器端且不会返回任何错误信息', done => {
const user = new User('纳尼')
user.save( err => {
if (err) done(err) // 如果返回错误码直接将错误码输出到控制台
else done()
})
})
})
})

优化,将done作为回调参数使用
describe('User', () => {
describe('#save()方法', () => {
it('应该成功保存到服务器端且不会返回任何错误信息', done => {
const user = new User('纳尼')
user.save(done)
})
})
})

使用promise的另一种替代方案就是将chai断言作为it的返回值,将chai断言作为一个promise对象返回
让Mocha进行链式处理,需要借助chai-as-promised库支持(https:www.npmjs.com/package/chai-as-promised)
在Mocha v3.0.0之后的版本中,如果直接构造ES6上的Promise对象则会被Mocha认为是非法的

it('应该完成此测试', done => {
return new Promise( resolve => {
assert.ok(true)
resolve()
}).then(done)
})
会提示异常信息

扩展:基于Nightwatch的端到端测试环境

端到端测试,简称e2e (End to End test):

***侧重于检测界面的交互效果与操作逻辑是否正确
{
1.单元测试侧重:检验函数的输出结果
2.e2e侧重:从用户视角,对真实系统的访问行为进行仿真
}

简单理解:

1.单元测试的功能只能确保单个组件的质量,无法测试具体的业务流程是否运作正常
2.e2e是面对 组件与组件之间、用户与真实环境之间的一种集成性测试

demo: https://github.com/Lee-Tanghui/Vue-Testing-Demo/issues
组件单元测试:https://blog.csdn.net/hsany330/article/details/73650020
***更多请参考官网例子:https://cn.vuejs.org/v2/guide/unit-testing.html


补充下:具体去google一下
Test-Driven Development(TDD)即测试驱动开发,一种测试先于编写代码的思想用于指导软件开发
Behavior Driven Development(BDD)行为驱动开发是一种敏捷软件开发的技术


单元测试(白盒测试),主要用于测试开发人员编写的代码是否正确,这部分工作都是开发人员自己来做的;通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为

BDD(灰盒测试、黑盒测试)

猜你喜欢

转载自www.cnblogs.com/dachengz/p/9776813.html