require('should');
const mylib = require('../index');
describe('My First Test', () => {
it('should get "Hello Tmall"', () => {
mylib().should.be.eql('Hello Tmall');
});
});
### nextTick
'use strict';
module.exports = (bu, callback) => process.nextTick(() => callback(`Hello ${bu}`));
由于源代码变成异步,所以测试用例就得做改造:
'use strict';
require('should');
const mylib = require('../index');
describe('My First Test', () => {
it('Welcome to Tmall', done => {
mylib('Tmall', rst => {
rst.should.be.eql('Hello Tmall');
done();
});
});
});
### promise
'use strict';module.exports = bu => new Promise(resolve => resolve(`Hello ${bu}`));
当然,如果是co党也可以直接使用co包裹:
'use strict';
const co = require('co');
module.exports = co.wrap(function* (bu) {
return `Hello ${bu}`;
});
对应的修改测试用例如下:
'use strict';
require('should');
const mylib = require('../index');
describe('My First Test', () => {
it('Welcome to Tmall', () => {
return mylib('Tmall').should.be.fulfilledWith('Hello Tmall');
});
});
###
页面测试
对于浏览器里跑的前端代码,做测试要比Node.js模块要麻烦得多。Node.js模块纯js代码,使用V8运行在本地,测试用的各种各样的依赖和工具都能快速的安装,而前端代码不仅仅要测试js,CSS等等,更麻烦的事需要模拟各种各样的浏览器,比较常见的前端代码测试方案有下面几种:
- 构建一个测试页面,人肉直接到虚拟机上开各种浏览器跑测试页面(比如公司的f2etest)。这个方案的缺点就是不好做代码覆盖率测试,也不好持续化集成,同时人肉工作较多
- 使用PhantomJS构建一个伪造的浏览器环境跑单元测试,好处是解决了代码覆盖率问题,也可以做持续集成。这个方案的缺点是PhantomJS毕竟是Qt的webkit,并不是真实浏览器环境,PhantomJS也有各种各样兼容性坑
- 通过Karma调用本机各种浏览器进行测试,好处是可以跨浏览器做测试,也可以测试覆盖率,但持续集成时需要注意只能开PhantomJS做测试,毕竟集成的Linux环境不可能有浏览器。这可以说是目前看到的最好的前端代码测试方式了
mocha.ui('bdd');
describe('Welcome to Tmall', function() {
before(function() {
window.render();
});
it('Hello', function() {
document.getElementById('tmall').textContent.should.be.eql('天猫前端招人,有意向的请发送简历至lingyucoder@gmail.com');
});
});
mocha.run();
使用PhantomJS进行测试
PhantomJS是一个模拟的浏览器,它能执行js,甚至还有webkit渲染引擎,只是没有浏览器的界面上渲染结果罢了。我们可以使用它做很多事情,比如对网页进行截图,写爬虫爬取异步渲染的页面,以及接下来要介绍的——对页面做测试。
当然,这里我们不是直接使用PhantomJS,而是使用mocha-phantomjs来做测试。npm install --save-dev mocha-phantomjs安装完成后,就可以运行命令./node_modules/.bin/mocha-phantomjs ./test/test.html来对上面那个test/test.html的测试了:
React组件源码src/index.jsx大概是这个样子:
import React from 'react';
class Welcome extends React.Component {
constructor() {
super();
}
render() {
return <div>{this.props.content}</div>;
}
}
Welcome.displayName = 'Welcome';
Welcome.propTypes = {
/**
* content of element
*/
content: React.PropTypes.string
};
Welcome.defaultProps = {
content: 'Hello Tmall'
};
module.exports = Welcome;
那么对应的test/index_spec.jsx则大概是这个样子:
import 'should';
import Welcome from '../src/index.jsx';
import ReactDOM from 'react-dom';
import React from 'react';
import TestUtils from 'react-addons-test-utils';
describe('test', function() {
const container = document.createElement('div');
document.body.appendChild(container);
afterEach(() => {
ReactDOM.unmountComponentAtNode(container);
});
it('Hello Tmall', function() {
let cp = ReactDOM.render(<Welcome/>, container);
let welcome = TestUtils.findRenderedComponentWithType(cp, Welcome);
ReactDOM.findDOMnode(welcome).textContent.should.be.eql('Hello Tmall');
});
});