本文全部資料請參考:github.com/antgod/reac…html
npm install --save-dev jest複製代碼
咱們先寫一個測試函數,有兩個數字參數作加法,首先,建立sum.js
文件node
function sum(a, b) {
return a + b
}
module.exports = sum複製代碼
而後,建立建立sum.test.js
,包含咱們目前的測試代碼。react
const sum = require('./sum');
test('adds 1 + 2 to equal 3', () => {
expect(sum(1, 2)).toBe(3);
});複製代碼
而後添加片斷到package.json中android
{
"scripts": {
"test": "jest"
}
}複製代碼
最後運行npm test
,jest輸入以下內容webpack
PASS ./sum.test.js
✓ adds 1 + 2 to equal 3 (5ms)複製代碼
你剛剛成功的編寫了一個jest測試!git
這個測試用例使用了expect
和toBe
進行兩個值相同的測試。想要學習更多的關於jest測試,請參考 Using Matcherses6
你也能夠直接從命令行執行,能夠輸入一些有空的參數(npm install jest -g)。github
Here's how to run Jest on files matching my-test, using config.json as a configuration file and display a native OS notification after the run:web
jest my-test --notify --config=config.json複製代碼
若是你想學習更多的命令行執行,請參考 Jest CLI Options正則表達式
使用 Babel:
安裝babel-jest
和 regenerator-runtime
包:
npm install --save-dev babel-jest regenerator-runtime複製代碼
注意: 若是你使用npm 3或者npm 4,你不用指明安裝regenerator-runtime
。
添加一份.babelrc
文件到你的工程根目錄,好比,若是你使用es6或者react.js須要使用babel-preset-es2015
和babel-preset-react
預設:
{
"presets": ["es2015", "react"]
}複製代碼
這樣你會使用es6與react全部指定的語法。
注意: 若是你使用更多的babel編譯配置,請使用babel's env option
,記住jest將會自動定義node_env做爲測試。
使用webpack
jest能夠實用在工程內使用webpack管理你的資產,樣式和編輯。webpack 提供一些特別的功能相比於其餘工具。更多資料請參考 webpack guide
jest使用matchers
讓你經過不一樣的方法測試值。你須要熟記不少不一樣的matchers
。這裏只介紹最經常使用的matchers
。
最簡單的測試值相等的是精確相等:
test('two plus two is four', () => {
expect(2 + 2).toBe(4);
});複製代碼
上段代碼,expect(2 + 2)
返回一個「期待」對象。除了調用matchers
,關於期待對象你不須要作太多。在這段代碼中,.toBe(4)
是一個matcher。當jest運行時,將追蹤全部失敗的matchers
,因此它能夠精確的打印錯誤信息。
toBe
使用===
精確等於測試。若是你想深度測試對象相等,使用toEqual
代替。
test('object assignment', () => {
const data = {one: 1};
data['two'] = 2;
expect(data).toEqual({one: 1, two: 2});
});複製代碼
toEqual
遞歸的查找每一個字段對比是否相等。
你可使用not
去測試matcher
的反面:
test('adding positive numbers is not zero', () => {
for (let a = 1; a < 10; a++) {
for (let b = 1; b < 10; b++) {
expect(a + b).not.toBe(0);
}
}
});複製代碼
有時候你須要判斷undefined,null與false,但有時候你不須要明確的區分他們。jest包含工具明確的區分他們。
舉個例子:
test('null', () => {
const n = null;
expect(n).toBeNull();
expect(n).toBeDefined();
expect(n).not.toBeUndefined();
expect(n).not.toBeTruthy();
expect(n).toBeFalsy();
});
test('zero', () => {
const z = 0;
expect(z).not.toBeNull();
expect(z).toBeDefined();
expect(z).not.toBeUndefined();
expect(z).not.toBeTruthy();
expect(z).toBeFalsy();
});複製代碼
你可使用這些matcher
作精確的匹配。
多種途徑比較數字
test('two plus two', () => {
const value = 2 + 2;
expect(value).toBeGreaterThan(3);
expect(value).toBeGreaterThanOrEqual(3.5);
expect(value).toBeLessThan(5);
expect(value).toBeLessThanOrEqual(4.5);
// toBe and toEqual are equivalent for numbers
expect(value).toBe(4);
expect(value).toEqual(4);
});複製代碼
你可使用toBeCloseTo
進行浮點比較
test('adding floating point numbers', () => {
const value = 0.1 + 0.2;
expect(value).not.toBe(0.3); // 浮點數不會直接相等
expect(value).toBeCloseTo(0.3); // 使用closeTo方法進行浮點數字比較
});複製代碼
你可使用toMatch
測試正則表達式來驗證string字符串
test('there is no I in team', () => {
expect('team').not.toMatch(/I/);
});
test('but there is a "stop" in Christoph', () => {
expect('Christoph').toMatch(/stop/);
});複製代碼
你能夠檢驗數組是否包含某一個特別項
const shoppingList = [
'diapers',
'kleenex',
'trash bags',
'paper towels',
'beer',
];
test('the shopping list has beer on it', () => {
expect(shoppingList).toContain('beer');
});複製代碼
你可使用toThrow
來檢驗函數是否拋出異常
function compileAndroidCode() {
throw new ConfigError('you are using the wrong JDK');
}
test('compiling android goes as expected', () => {
expect(compileAndroidCode).toThrow();
expect(compileAndroidCode).toThrow(ConfigError);
// You can also use the exact error message or a regexp
expect(compileAndroidCode).toThrow('you are using the wrong JDK');
expect(compileAndroidCode).toThrow(/JDK/);
});複製代碼
這是一個just嘗試,查看完整的matchers
列表renerence docs。
一旦你掌握了一個可用的matcher
,建議下一步學習jest如何檢驗異步代碼
js運行異步代碼是很廣泛的。jest
須要知道何時代碼測試已完成,才能移動到下一個測試。jest
有幾種方法處理。
最廣泛的異步是經過回調函數。
好比,若是你調用fetchData(callback)
函數去拉取異步數據而且結束時候調用callback(data)
。你要測試的數據是否等於peanut buter
。
默認狀況下,Jest
走完測試代碼就完成測試。這意味着測試不能定期進行。
// Don't do this!
test('the data is peanut butter', () => {
function callback(data) {
expect(data).toBe('peanut butter');
}
fetchData(callback);
});複製代碼
問題在於測試工做將在fetchData
結束的時候,也就是在回調函數以前結束。
爲了解決這個問題,這是另外一種形式。使用參數done
來代替無參函數。Jest
將會延遲測試直到done
回調函數執行完畢。
test('the data is peanut butter', done => {
function callback(data) {
expect(data).toBe('peanut butter');
done();
}
fetchData(callback);
});複製代碼
若是done
一直沒有調用,測試將會失敗。
若是你使用promise,有一種簡單的方法處理異步測試。你的測試代碼中Jest
返回一個Promise
,而且等待Promise
去resolve
。若是Promise
是rejected
,測試自動失敗。
好比,仍是那個fetchData
,此次使用了回調,返回一個promise
假定reslove
一個字符串peanut butter
。測試代碼以下:
test('the data is peanut butter', () => {
return fetchData().then(data => {
expect(data).toBe('peanut butter');
});
});複製代碼
確保返回一個Promise-若是你省略了return
,你的測試代碼將會在fetchData
以前結束。
你也可使用resolves
關鍵字在你的expect
代碼後,而後Jest
將會把等待狀態轉換成resolve
。若是promise
被rejected
,測試自動失敗。
test('the data is peanut butter', () => {
return expect(fetchData()).resolves.toBe('peanut butter');
});複製代碼
若是你使用async/await
,你能夠完美嵌入測試。寫一個async
測試,僅使用async
關鍵字在你的matchers
函數前面就能經過測試。好比,仍是fetchData
這個測試方案能夠寫成
test('the data is peanut butter', async () => {
await expect(fetchData()).resolves.toBe('peanut butter');
});複製代碼
在這種狀況下,async/await
僅僅是個有效的promises
樣例的邏輯語法糖。
這些表單特別優秀,你能夠混合使用這些在你的代碼庫或者單個文件中,它僅僅使你的測試變得更加簡單。
寫測試的過程當中,在你運行測試以前,你須要作一些初始化工做,去作一些須要測試的事情以前,而且你須要作一些結束工做,去作一些測試結束的事情。Jest
提供了helper
函數去處理這些工做。
若是你有不少測試有重複的工做,你能夠是使用beforeEach
與afterEach
。
好比你有不少測試運行以前須要調用initializeCityDatabase()
,並且測試結束 後須要調用clearCityDatabase()
。你能夠這麼作:
beforeEach(() => {
initializeCityDatabase();
});
afterEach(() => {
clearCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});複製代碼
一樣的,若是你的initializeCityDatabase
函數返回一個promise
,你可使用return
返回這個函數。
beforeEach(() => {
return initializeCityDatabase();
});複製代碼
若是你有不少測試有共同的重複的工做,而且重複的工做只在測試開始與測試結束的地方運行一次,你能夠是使用beforeAll
與beforeAll
。
好比你有一個測試開始以前要調用initializeCityDatabase()
,並且測試結束 後須要調用clearCityDatabase()
。你能夠這麼作:
beforeAll(() => {
return initializeCityDatabase();
});
afterAll(() => {
return clearCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});複製代碼
默認狀況下,before
與after
會對文件的每一個測試生效。若是你只想對某些測試生效,你可使用describe
塊。 before
與after
僅僅會在聲明塊中運行。
好比,咱們不只須要城市初始化,還須要食物初始化,咱們能夠對不一樣的測試作不一樣的初始化。
// Applies to all tests in this file
beforeEach(() => {
return initializeCityDatabase();
});
test('city database has Vienna', () => {
expect(isCity('Vienna')).toBeTruthy();
});
test('city database has San Juan', () => {
expect(isCity('San Juan')).toBeTruthy();
});
describe('matching cities to foods', () => {
// Applies only to tests in this describe block
beforeEach(() => {
return initializeFoodDatabase();
});
test('Vienna <3 sausage',="" ()=""> {
expect(isValidCityFoodPair('Vienna', 'Wiener Schnitzel')).toBe(true);
});
test('San Juan <3 plantains',="" ()=""> {
expect(isValidCityFoodPair('San Juan', 'Mofongo')).toBe(true);
});
});
複製代碼
若是你僅僅想測試一個測試用例,或者跨過某個測試用例,你可使用fit
與xit
。
fit('this will be the only test that runs', () => {
expect(true).toBe(false);
});
xit('this will be the only test that runs', () => {
expect(true).toBe(false);
});
test('this test will not run', () => {
expect('A').toBe('A');
});複製代碼