React Jest 介紹與實作

Jest 是個 JS 的測試工具
其實還有 Jasmine 跟其他的工具
既然 FB 內部是使用 Jest
我們就來看看 Jest 怎麼使用

前提

既然要使用測試工具
當然要有東西給我們測試
那就來拿個 react-bootstrap-input-field 來做測試吧

測試功能:
1. 只允需輸入數字
2. 測試錯誤的 email
3. 測試對的 email

(開始之前請使用 Mitch 的 react-boilerplate

準備及安裝 JEST

在剛剛使用 react-boilerplate 安裝好的目錄下:

npm install jest-cli — save-dev

在 src/app/component 目錄下
加入 react-bootstrap-input-field 的 src/app/components/input-field.js
這樣我們就有個 component 可以測試了

接下來我們還需要在 package.json 裡面加入以下的資訊

“dependencies”: { 
“react”: “*”, “react-tools”: “*”
},
“jest”: {
“scriptPreprocessor”: “<rootDir>/preprocessor.js”,
“unmockedModulePathPatterns”: [“<rootDir>/node_modules/react”] }

最後我們需要加個目錄 __tests__ (前後各兩個雙底線)
此目錄是要告訴 jest 需要跑這裡面的測試程式

/src/app/components/input-field.js ->component to be tested
/src/app/components/__tests__/input-field-test.js -> test logic

JEST 解析

首先 jest 的架構大概會長這樣:

jest.dontMock('../input-field');
describe('InputField', function() {
it('should not allow any other key except number when in number mode', function() {
...
});

第一行相當重要
這是要告訴 jest 不要假的 module(要真的 module 來測)
describe 為 module 的名字(當然你想要放女朋友的名字也可以)
接下來 it(‘…’) 就是寫這個測試的敘述
所以當有錯誤發生的時候你可以知道在哪裡發生什麼事

接下來我們就要真的開始寫我們的測試了
react-bootstrap-input-field 有個只允許數字的功能
當使用者輸入字母會把輸入值過濾掉

var React = require('react/addons'),
InputField = require('../input-field'),
TestUtils = React.addons.TestUtils,
source;
var handleChange = function(name, value, isValid) {
expect(value).toEqual('123');
};
// number only
source = TestUtils.renderIntoDocument(
<InputField name="NumberOnly" inputType="number" onChange={handleChange} />
);
var numberOnlyComponent =    TestUtils.findRenderedDOMComponentWithTag(source, 'input');
TestUtils.Simulate.change(numberOnlyComponent.getDOMNode(), { target: { value: 'a123ab' } });

我們先看中間的<InputField … onChange={handleChange} />
也就是說當使用者輸入此功能會被呼叫
而最下面那行 … target: { value: ‘a123ab’ } 也就是模擬輸入
最後 expect(value).toEqual(‘123’) 也就是我們期望的值。
若是不相同的話 test 就會發出錯誤

接下來我們來測 email 的部分

it('should filter good and bad email', function() {
var React = require('react/addons'),
InputField = require('../input-field'),
TestUtils = React.addons.TestUtils,
source;
var handleChange = function(name, value, isValid) {
if(name === 'badEmail') {
console.log(name, value);
expect(isValid).toEqual(true);
}
else if(name === 'goodEmail') {
console.log(name, value);
expect(isValid).toEqual(true);
}
};
// bad email
source = TestUtils.renderIntoDocument(
<InputField name="badEmail" inputType="email" onChange={handleChange} />
);
var badEmail = TestUtils.findRenderedDOMComponentWithTag(source, 'input');
TestUtils.Simulate.change(badEmail.getDOMNode(), { target: { value: 'a123ab' } });
// good email
source = TestUtils.renderIntoDocument(
<InputField name="goodEmail" inputType="email" onChange={handleChange} />
);
var goodEmail = TestUtils.findRenderedDOMComponentWithTag(source, 'input');
TestUtils.Simulate.change(goodEmail.getDOMNode(), { target: { value: 'mickey@disney.com' } });
});

這裏的 email 判斷是用回傳的 isValid 參數來做判斷的
expect(isValid).toEqual(true)
而正確的 email 形式為 [string]@[string] (先簡單做)

完整的 git

Show your support

Clapping shows how much you appreciated Jim Kang’s story.