1于置、Mocha測試掃盲
a、測試腳本里面應(yīng)該包括一個或多個describe塊,每個describe塊應(yīng)該包括一個或多個it塊嚼松。
// add.js
function add(x, y) {
return x + y;
}
module.exports = add;
// add.test.js
var add = require('./add.js');
var expect = require('chai').expect; // 引入斷言庫 chai , Mocha本身不提供(Mocha并不限制使用哪一種斷言庫)
describe('加法函數(shù)的測試', function() {
it('1 加 1 應(yīng)該等于 2', function() {
expect(add(1, 1)).to.be.equal(2);
});
});
b、describe塊稱為"測試套件"(test suite)锰扶,表示一組相關(guān)的測試献酗。它是一個函數(shù),第一個參數(shù)是測試套件的名稱("加法函數(shù)的測試")坷牛,第二個參數(shù)是一個實際執(zhí)行的函數(shù)罕偎。
c、it塊稱為"測試用例"(test case)京闰,表示一個單獨的測試颜及,是測試的最小單位甩苛。它也是一個函數(shù),第一個參數(shù)是測試用例的名稱("1 加 1 應(yīng)該等于 2")俏站,第二個參數(shù)是一個實際執(zhí)行的函數(shù)讯蒲。
d、expect斷言的寫法都是一樣的肄扎。頭部是expect方法爱葵,尾部是斷言方法,比如equal反浓、a/an萌丈、ok、match等雷则。兩者之間使用to或to.be連接辆雾。
// 相等或不相等
expect(4 + 5).to.be.equal(9);
expect(4 + 5).to.be.not.equal(10);
expect(foo).to.be.deep.equal({ bar: 'baz' });
// 布爾值為true
expect('everthing').to.be.ok;
expect(false).to.not.be.ok;
// typeof
expect('test').to.be.a('string');
expect({ foo: 'bar' }).to.be.an('object');
expect(foo).to.be.an.instanceof(Foo);
// include
expect([1,2,3]).to.include(2);
expect('foobar').to.contain('foo');
expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
// empty
expect([]).to.be.empty;
expect('').to.be.empty;
expect({}).to.be.empty;
// match
expect('foobar').to.match(/^foo/);
e、mocha --recursive 命令會執(zhí)行test目錄下的所有test測試腳本
f月劈、異步測試:Mocha默認(rèn)每個測試用例最多執(zhí)行2000毫秒度迂,如果到時沒有得到結(jié)果,就報錯猜揪。對于涉及異步操作的測試用例惭墓,這個時間往往是不夠的,需要用-t或--timeout參數(shù)指定超時門檻(mocha -t 5000 timeout.test.js)
g而姐、Mocha內(nèi)置對Promise的支持腊凶,允許直接返回Promise,等到它的狀態(tài)改變拴念,再執(zhí)行斷言钧萍,而不用顯式調(diào)用done方法
it('異步請求應(yīng)該返回一個對象', function() {
return fetch('https://api.github.com')
.then(function(res) {
return res.json();
}).then(function(json) {
expect(json).to.be.an('object');
});
});
h、大型項目有很多測試用例政鼠。有時风瘦,我們希望只運行其中的幾個,這時可以用only方法公般。describe塊和it塊都允許調(diào)用only方法万搔,表示只運行某個測試套件或測試用例。
it.only('1 加 1 應(yīng)該等于 2', function() {
expect(add(1, 1)).to.be.equal(2);
});
2官帘、React 單元測試
a瞬雹、一個React組件有兩種存在形式:虛擬DOM對象(即React.Component的實例)和真實DOM節(jié)點。官方測試工具庫對這兩種形式遏佣,都提供測試解決方案挖炬。
Shallow Rendering:測試虛擬DOM的方法(將一個組件渲染成虛擬DOM對象,但是只渲染第一層,不渲染所有子組件)
DOM Rendering: 測試真實DOM的方法
b意敛、Enzyme庫:官方測試工具庫的封裝馅巷,它模擬了jQuery的API,非常直觀
// 1草姻、shallow
import {shallow} from 'enzyme';
describe('Enzyme Shallow', function () {
it('App\'s title should be Todos', function () {
let app = shallow(<App/>);
expect(app.find('h1').text()).to.equal('Todos');
});
};
// 2钓猬、render(將React組件渲染成靜態(tài)的HTML字符串,然后分析這段HTML代碼的結(jié)構(gòu)撩独,返回一個對象)
// 適用于依賴類名做測試
import {render} from 'enzyme';
describe('Enzyme Render', function () {
it('Todo item should not have todo-done class', function () {
let app = render(<App/>);
expect(app.find('.todo-done').length).to.equal(0);
});
});
// 3敞曹、mount(將React組件加載為真實DOM節(jié)點,要求存在一個真實的DOM環(huán)境综膀,否則會報錯澳迫。因此,測試用例之中剧劝,DOM環(huán)境(即window, document 和 navigator 對象)必須是存在的橄登,[jsdom](https://github.com/tmpvar/jsdom) 庫提供這項功能。)
// 修改package.json的test字段如下:
{
"scripts": {
"test": "mocha --compilers js:babel-core/register --require ./test/setup.js",
},
}
// setup.js
import jsdom from 'jsdom';
if (typeof document === 'undefined') {
global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = document.defaultView;
global.navigator = global.window.navigator;
}
// test.js
import {mount} from 'enzyme';
describe('Enzyme Mount', function () {
it('Delete Todo', function () {
let app = mount(<App/>);
let todoLength = app.find('li').length;
app.find('button.delete').at(0).simulate('click');
expect(app.find('li').length).to.equal(todoLength - 1);
});
});
c讥此、Enzyme的常用API
.get(index):返回指定位置的子組件的DOM節(jié)點
.at(index):返回指定位置的子組件
.first():返回第一個子組件
.last():返回最后一個子組件
.type():返回當(dāng)前組件的類型
.text():返回當(dāng)前組件的文本內(nèi)容
.html():返回當(dāng)前組件的HTML代碼形式
.props():返回根組件的所有屬性
.prop(key):返回根組件的指定屬性
.state([key]):返回根組件的狀態(tài)
.setState(nextState):設(shè)置根組件的狀態(tài)
.setProps(nextProps):設(shè)置根組件的屬性