Jestとは
jasmineの後継テスティングフレームワーク。
CRAに予め組み込まれてはいるが、最新のバージョンではないため、明示的にインストールする。
npm i --save-dev jest
npm (run) test
だとCRAにデフォルトで組み込まれているバージョンのjestを使用してしまうので、明示的にjest
コマンドを実行するよう書き換える。
package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "jest", //jestを実行するよう書き換える
"eject": "react-scripts eject"
},
Enzymeとは
Airbnb社が提供しているReactのコンポーネントテストツール。コンポーネントをshallow
(浅いコピー)、mount
(ディープコピー)して非破壊のままUIのテストができる。
Enzymeのインストール
enzymeと使用しているReactのバージョンに合わせたアダプタをインストールする。
npm i --save-dev enzyme enzyme-adapter-react-16
setupTests.js
を作成し、アダプタを初期化する処理を記述する。
setupTests.js
import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import '@babel/polyfill';
Enzyme.configure({ adapter: new Adapter() });
babelを使用するための準備をする
ReactJS、VueJSなどで使われているJSX
をjestが解釈するためにbabelが必要。
必要なライブラリのインストール
npm i --save-dev @babel/polyfill @babel/preset-env @babel/preset-react babel-core babel-jest
設定を記述する
babel.config.js
module.exports = {
"presets": ['@babel/preset-env', '@babel/preset-react'],
"plugins": [
"@babel/plugin-proposal-class-properties"
]
}
package.jsonにJestのコンフィグを記述する
テストを起動する際にsetupTests.js
を読み込む設定
package.json
{
"jest": {
"setupFilesAfterEnv": [
"<rootDir>/src/setupTests.js"
]
}
}
テストの対象からCSSを除外する
この設定を書かないとCSSもjsとして認識され、実行エラーとなる。
package.json
{
"jest":{
//ts・jsなどはbabel-jestで処理する
//静的ファイルはstyleMock.jsで処理する
"transform": {
"^.+\\.(ts|tsx|js)?$": "babel-jest",
"^.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$": "identity-obj-proxy"
},
//node_modulesは無視する
"transformIgnorePatterns": [
"/node_modules/"
],
"moduleNameMapper": {
"^.+\\.(css|less)$": "<rootDir>/src/__mocks__/styleMock.js"
}
}
}
styleMock.jsでは何も返さない処理を記述する。
styleMock.js
module.exports = {};
コンポーネントテストの書き方
要素が正しくレンダリングされているかどうかの確認
Sample.spec.js
(import宣言省略)
//test起動時に毎回行う処理
beforeEach(()=>{
....
})
describe('Sampleコンポーネントのテスト',()=>{
it('FormGroupが存在すること',() => {
const wrapper = mount(
<Provider store={store}>
<Sample/>
</Provider>
);
//FormGroupの要素が1つレンダリングされること
expect(wrapper.find(FormGroup).length).toBe(1);
})
})
クラスの中のメソッドの動作の確認
it('maxLengthの最大値を超えた場合のバリデーションができること',() => {
const wrapper = mount(
<Sample/>
);
//stateに値をセットする
wrapper.setState({
value: {
length:9
}
});
let result = wrapper.instance().
expect(result).toBe('error');
});
stateの中身を検証する
it("stateに初期値がセットされていること", () => {
//stateの中身を監視する
const setStateSpy = jest.spyOn(*****.prototype, 'setState');
const props = {
data: {
attr:'fugafuga'
},
name:'hogehoge',
}
};
const wrapper = mount(
<Provider store={store}>
<Sample {...props} />
</Provider>
);
//stateの中身を検証する
expect(setStateSpy).toHaveBeenCalledWith({
name:'hogehoge',
attr:'fugafuga'
})
});
カバレッジの出し方
・jestがグローバルインストールされている場合
$ jest --collectCoverage