LoginSignup
21
9

More than 5 years have passed since last update.

React Tutorial Example (Jest)

Last updated at Posted at 2016-12-07

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 にしましょう!

21
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
9