单元测试的工具们
单元测试框架
* Qunit - jquery的单测工具
- jasmine - 早期的测试框架
- mocha - 常用框架 支持BDD和TDD
- Cucumber - 语义化更好的测试工具
断言
* chai
集成
* Karma
- jenkins
- travis-ci
mock
* sinon
- supertest
组件测试框架
* polymer的单测工具:web-component-tester
- react的单测工具:Jest
之前的博客对比较基础的测试工具都有所介绍,参考前端自动化测试基础篇,在这篇blog中,我们首先了解一下polymer组件的单元测试工具。
why web-component-tester
web-component-tester是polymer组件用于单元测试的框架,主要是用作对于html文件的测试
- 它内部集成了mocha、sinon、sinon-chai、chai,方便使用
- 使用lodash作为工具函数
- async用作异步函数的测试
- test-fixture作为模板的测试
- accessibility-developer-tools将测试结果输出到命令行中。
- 在server端wct内置selenium-standalone,在客户端使用wd.js操作服务器进行测试
API方法
基本API
- WCT.loadSuites可以将
- suite类似describe将测试进行归类
- test类似it进行具体的测试
assert用于进行断言,断言同chai的assert的断言规则
suite(‘AwesomeLib’, function() {
test(‘is awesome’, function() {assert.isTrue(AwesomeLib.awesome);//TDD模式
});
});
`特殊的方法
text-fixture 用来在测试过程中操作template中的dom元素,用法是在外部用
包裹起来。然后就可以通过
fixture获取元素,按照dom进行操作。`<test-fixture id="simple"> <template> <div></div> </template> </test-fixture> <script> suite('classList', function() { var div; setup(function() { div = fixture('simple'); }) test('foo', function() { div.classList.add('foo'); assertSomethingOrOther(div); }); }); </script> `
关于template binding异步的测试
异步测试在javascript的世界中可谓最常见,对于polymer组件来说,数据驱动模板刷新很重要,
模板数据的刷新会调用Polymer.dom.flush, 它是个异步的过程,对此 web-components-tester 专门提供
flush函数处理此类异步。`suite('with two selected items', function() { // Clean up after ourselves. teardown(function(done) { s.clearSelection(); s.multi = false; // Wait for observers to resolve before moving on to more tests. flush(done); }); test('multi selects by index', function(done) { s.multi = true; //数据变化 s.selected = [0, 2]; flush(function() { //模板刷新 assert.equal(s.selectedIndex, [0, 2]); assert(s.children[0].classList.contains('core-selected')); assert(!s.children[1].classList.contains('core-selected')); assert(s.children[2].classList.contains('core-selected')); done(); }); }); }); `
google map component测试实例
代码参考,f2e test
- 1、安装 web-components-tester: npm install -g web-component-tester
2 建立test文件夹(默认地址)
* 2.1 index.html
- 2.2 google-map-marker.html
- 2.3 marker.js
` suite('markers default', function () { var map; setup(function () { map = document.querySelector('#map'); }); test('markers are initialized', function () { var markerEl = Polymer.dom(map).querySelector('google-map-marker'); assert.isUndefined(markerEl.marker); assert.isUndefined(markerEl.map); assert.isNull(markerEl.info); assert.equal(markerEl.latitude, 37.779); assert.equal(markerEl.longitude, -122.3892); }); test('markers are added to map', function () { map.addEventListener('google-map-ready', function () { var mapMarkerEl = Polymer.dom(map).querySelector('google-map-marker'); var firstMarker = map.markers[0]; expect(firstMarker).to.deep.equal(mapMarkerEl); assert.equal(map.markers.length, 3); }); }); test('markers position can be updated', function (done) { map.addEventListener('google-map-ready', function (e) { var markerEl = Polymer.dom(map).querySelector('google-map-marker'); markerEl.latitude = 37.79493; markerEl.longitude = -122.41942; markerEl.zIndex = 1; assert.equal(markerEl.map, map.map, "marker's map is not the google-map's"); //重新渲染 异步过程 Polymer.dom.flush(); async.nextTick(function () { var marker = markerEl.marker; assert.equal(marker.getPosition().lat(), markerEl.latitude); assert.equal(marker.getPosition().lng(), markerEl.longitude); assert.equal(marker.getZIndex(), markerEl.zIndex); done(); }); }); }); }); `
3 运行测试脚本 wct 即可。
wct运行机制
代码:runner
- 建立webserver,模板参见index.html
- 读取wct.conf.json配置
- 内置selenium server 通过wd.js建立连接打开浏览器进行测试
- 并将结果通过socketIO返回显示在命令行
- 测试框架核心:browser.js, 源码内置chai mocha sinon socket等以及polymer测试的辅助函数
辅助工具
在测试中少不了点击事件的模拟,wct这个工具不具有这个功能,但是可以使用polymer的工具组件iron-test-helpers
它内置了MockInteraction可以实现各个事件的模拟,只需import iron-test-helpers.html 即可。使用方法如下:`test(‘can be triggered with space’, function(done) {
button.addEventListener(‘keydown’, function() {done();
});
MockInteractions.pressSpace(button);
});test(‘can be clicked’, function(done) {
button.addEventListener(‘click’, function() {done();
});
MockInteractions.tap(button);
});