React や Redux は Jest という JavaScript の Testing Framework が利用されています。
Actions, Reducers のテストはもちろん、Components のテストもできるので便利です。
前回 のアプリケーションに テスト を実装してみましょう。
Learning
- Jest で Actions, Reducers のテストをする。
- Enzyme で Components のテストをする。
Environment
- node: v6.9.1
- npm: v4.0.3
- yarn: v0.18.0
Comment Box Form
- 完成される Source Code のファイルリストです。
$ tree -a -I node_modules
.
├── .babelrc
├── app
│ ├── actions
│ │ └── index.js
│ ├── components
│ │ ├── Comment
│ │ │ └── index.js
│ │ ├── CommentBox
│ │ │ ├── index.js
│ │ │ └── style.css
│ │ ├── CommentForm
│ │ │ └── index.js
│ │ ├── CommentList
│ │ │ └── index.js
│ │ └── global.css
│ ├── containers
│ │ └── App
│ │ ├── index.js
│ │ └── style.css
│ ├── index.js
│ ├── reducers
│ │ └── index.js
│ └── store
│ └── index.js
├── test
│ └── app
│ ├── actions
│ │ └── index.test.js
│ ├── components
│ │ ├── Comment
│ │ │ └── index.test.js
│ │ └── CommentBox
│ │ └── index.test.js
│ └── reducers
│ └── index.test.js
├── index.html
├── package.json
├── webpack.config.js
└── yarn.lock
Let's hands-on
Setup application
-
git clone
コマンドでアプリケーションをダウンロードします。 -
yarn
コマンドで依存するモジュールをインストールします。
$ git clone https://github.com/ogom/react-comment-box-example.git
$ cd react-comment-box-example
$ git checkout package
$ yarn
Jest
- Jest のモジュールをインストールします。
- redux の Writing Tests を参考にしました。
$ yarn add --dev jest babel-jest
-
package.json
のscripts
にtest
を記述します。
package.json
"scripts": {
"start": "webpack-dev-server -d --progress --colors",
- "test": "echo \"Error: no test specified\" && exit 1"
+ "test": "jest",
+ "test:watch": "npm test -- --watch"
},
-
yarn test
コマンドでテストを実行します。- まだテストを書いていないので、
No tests found
が表示されます。
- まだテストを書いていないので、
$ yarn test
No tests found
-
yarn run test:watch
コマンドでファイルの変更を監視します。
$ yarn run test:watch
No tests found related to files changed since last commit.
Press `a` to run all tests, or run Jest with `--watchAll`.
Watch Usage
› Press a to run all tests.
› Press o to only run tests related to changed files.
› Press p to filter by a filename regex pattern.
› Press q to quit watch mode.
› Press Enter to trigger a test run.
それでは、監視した状態でテストを書いてみましょう!
Actions
-
describe
に 概要や機能 を記述します。it
には 期待 を記述します。-
expect
に 観察の対象 を記述します。toEqual
に 期待の結果 を記述します。
-
-
expect
に Action を記述してtoEqual
に Create されるtype
やpayload
を記述します。
test/app/actions/index.test.js
import * as actions from '../../../app/actions'
describe('actions', () => {
it('should create an action to show the comments', () => {
const value = []
const expectedAction = {
type: 'show_comments',
payload: value
}
expect(
actions.showComments(value)
).toEqual(
expectedAction
)
})
it('should create an action to add a comment', () => {
const value = {foo: '123', bar: '456'}
const expectedAction = {
type: 'add_comment',
payload: value
}
expect(
actions.addComment(value)
).toEqual(
expectedAction
)
})
})
- テストを実行すると
describe
とit
が出力されます。
PASS test/app/actions/index.test.js
actions
✓ should create an action to show the comments (4ms)
✓ should create an action to add a comment (1ms)
Reducers
-
expect
に Reducer を記述してtoEqual
に State を記述します。- Action の実行で State の変更を確認できる、このテストは大切です。
test/app/reducers/index.test.js
import * as actions from '../../../app/actions'
import reducers from '../../../app/reducers'
describe('reducers', () => {
let state
beforeEach(() => {
state = [undefined]
})
it('should return the initial state', () => {
expect(
reducers(undefined, {type: ''})
).toEqual(
state
)
})
it('should return the show comments', () => {
const value = [{foo: '123', bar: '456'}]
state = value
expect(
reducers(undefined, actions.showComments(value))
).toEqual(
state
)
})
it('should return the add a comment', () => {
const value = {foo: '123', bar: '456'}
state = [value]
expect(
reducers(undefined, actions.addComment(value))
).toEqual(
state
)
})
})
Components
- Enzyme のモジュールをインストールします。
- Jest Tutorial - webpack を参考にしました。
$ yarn add --dev enzyme react-addons-test-utils
Comment
-
expect
に Component を記述してtoBe
に 期待値 を記述します。
test/app/components/Comment/index.test.js
import React from 'react'
import { shallow } from 'enzyme'
import Comment from '../../../../app/components/Comment'
describe('components', () => {
describe('Comment', () => {
const wrapper = shallow(<Comment author={'foo'}>{'bar'}</Comment>)
it('should return author and comment', () => {
expect(wrapper.find('.commentAuthor').text()).toBe('foo')
expect(wrapper.find('span').render().find('p').text()).toBe('bar')
})
})
})
CommentBox
-
CSS Modules は
identity-obj-proxy
でモックを利用します。
$ yarn add --dev identity-obj-proxy
-
package.json
のjest
にmoduleNameMapper
を記述します。
package.json
+ "jest": {
+ "moduleNameMapper": {
+ "\\.css$": "identity-obj-proxy"
+ }
+ },
- CSS を含む Component のテストも実行できます。
test/app/components/CommentBox/index.test.js
import React from 'react'
import { shallow } from 'enzyme'
import CommentBox from '../../../../app/components/CommentBox'
describe('components', () => {
describe('CommentBox', () => {
const wrapper = shallow(<CommentBox/>)
it('should return the Comments', () => {
expect(wrapper.find('h1').text()).toBe('Comments')
})
})
})
- 最後に
yarn test
で全て PASS するか確認しましょう。
$ yarn test
PASS test/app/components/Comment/index.test.js
PASS test/app/components/CommentBox/index.test.js
PASS test/app/reducers/index.test.js
PASS test/app/actions/index.test.js
Test Suites: 4 passed, 4 total
Tests: 7 passed, 7 total
Snapshots: 0 total
Time: 1.461s
Ran all test suites.
✨ Done in 1.96s.
Congrats!
テストは設計フェーズや保守フェーズで、利用の方法によってはとても便利な機能です。
次回は electron で native application にしましょう!