1. Qiita
  2. 投稿
  3. Node.js
  • 14
    いいね
  • 0
    コメント

ReactReduxJest という 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

$ yarn add --dev jest babel-jest
  • package.jsonscriptstest を記述します。
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期待の結果 を記述します。
  • expectAction を記述して toEqualCreate される typepayload を記述します。
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
    )
  })
})
  • テストを実行すると describeit が出力されます。
 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

  • expectReducer を記述して toEqualState を記述します。
    • 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

$ yarn add --dev enzyme react-addons-test-utils

Comment

  • expectComponent を記述して 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 Modulesidentity-obj-proxy でモックを利用します。
$ yarn add --dev identity-obj-proxy
  • package.jsonjestmoduleNameMapper を記述します。
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 にしましょう!

Comments Loading...