Reactを使ったアプリのテストにはjestっていうのが使われるっぽいですね?jest知らない子だ。
Mock by Defaultとか激しいですね。
軽く使ってみる
テスト対象のスクリプトのあるフォルダに__tests__というフォルダを作ってその下に「***-test.js」という感じでファイルを作るっぽいですね。
インストール
React以外に、以下のものをインストールしておきます。最後のやつはReactをテストするときの便利メソッドとかが定義されてるものです。
npm install jest-cli -g npm install jest tsd install jest tsd install react-addons-test-utils
Test Hello world
ということで以下のような足し算するクラスを作ってみました。scripts\Calc.tsという名前で
exportdefaultclass Calc { add(x: number, y: number) {return x + y; }}
そして、scripts\__tests__\Calc-test.tsという名前で以下のようなファイルを作ります。
/// <reference path="../../typings/jest/jest.d.ts" /> jest.dontMock('../Calc'); import Calc from '../Calc'; describe('calc', () => { it('add', () => { expect(12).toEqual(new Calc().add(10, 2)); }); });
まず、jest.dontMockでモックにしないモジュールを指定します。その後、テスト対象のモジュールを読み込みます。
describeでテストクラスを定義するようなイメージで、itでテストメソッドを定義するようなイメージです。expectでテストの期待値を指定してto***メソッドでアサーションするという感じです。
Reactのテストは
以下のようなコンポーネントをテストすることを考えてみます。
scripts\Header.tsxという名前でファイルを作ります。
import * as React from 'react'; interface HeaderProps extends React.Props<{}> { title: string; onClick: () => void; }exportdefaultclass Header extends React.Component<HeaderProps, {}> { render() {return ( <div> <h1>{this.props.title}</h1> <hr /> <button onClick={() => this.props.onClick()}>OK</button> </div> ); }}
そして、テスト用のファイルとしてscripts\__tests__\Header-test.tsxを作ります。tsxなところ注意。
/// <reference path="../../typings/jest/jest.d.ts" />import * as React from 'react'; import * as ReactDOM from 'react-dom'; import TestUtils = require('react-addons-test-utils'); jest.dontMock('../Header'); import Header from '../Header'; describe('header test', () => { it('title', () => {var mockHandler = jest.genMockFunction(); var h = TestUtils.renderIntoDocument( <Header title='Hello' onClick={mockHandler}/> ); var h1 = TestUtils.findRenderedDOMComponentWithTag(h, 'h1'); expect(h1.textContent).toEqual('Hello'); var button = TestUtils.findRenderedDOMComponentWithTag(h, 'button'); TestUtils.Simulate.click(button); expect(mockHandler).toBeCalled(); }); });
まず、react系のものを読み込んでおきます。react-addons-test-utilsはテスト用です。そして、先ほど作ったHeaderをモックにしないように指定してからimportします。
itの中ではjest.getMockFunction()でモックのファンクションを作ってから、TestUtils.renderIntoDocumentメソッドでReactのコンポーネントを作ります。このとき、onClickに先ほど作ったモックのファンクションを渡します。
TestUtilsのfindRenderedDOMComponentWithTagでコンポーネントからタグを取り出せます。textContentを使って中身のアサーションをしたり、TestUtils.Simulate.clickでボタンのクリックをシミュレートしてtoBeCalledでモックのファンクションが呼び出されたことなどをアサーションできます。
package.jsonの指定
Reactのファイルがモックにされないようにpackage.jsonに以下の行を追加しておきます。
"jest": {"unmockedModulePathPatterns": ["<rootDir>/node_modules/react", "<rootDir>/node_modules/fbjs"]}
実行の準備
package.json scriptsのところにtestを追加します。デフォルトで何も指定しないとechoが仕込まれてるはずなので、以下のように書き換えます。
"scripts": {"test": "jest"},
実行
PowerShellあたりでnpm testと打ち込むと以下のようにテストが実行されます。
> jest Using Jest CLI v0.8.2, jasmine1 PASS scripts\__tests__\Calc-test.js (0.033s) PASS scripts\__tests__\Header-test.js (0.539s) 2 tests passed (2 total in 2 test suites, run time 1.519s)
所感
Visual Studioのテストランナーとのインテグレーションをしてくれるものはないっぽいので、適当に自分で手打ちするしかなさそうです。こういうのが増えてくると、タスクランナーがほしくなってくるんでしょうね。まだ、大丈夫。
package.json全体
一応jestの定義とかあるので、全体を載せておきます。
{"name": "helloworld", "version": "1.0.0", "description": "", "main": "scripts/app.js", "scripts": {"test": "jest"}, "author": "", "license": "ISC", "dependencies": {"jest": "^0.1.40", "react": "^0.14.5", "react-addons-test-utils": "^0.14.5", "react-dom": "^0.14.5"}, "jest": {"unmockedModulePathPatterns": ["<rootDir>/node_modules/react", "<rootDir>/node_modules/fbjs"]}}