ES6+Reactをkarma+mocha+chaiでテストした時の設定まとめ

## やりたいこと
* Reactコンポーネントのテスト
* テストカバレッジ出力

## 設定後のテスト結果出力
```
START:
  ListView
    ✔ propsが正しく設定できる

Finished in 0.017 secs / 0.008 secs

SUMMARY:
✔ 1 test completed
--------------|----------|----------|----------|----------|----------------|
File          |  % Stmts | % Branch |  % Funcs |  % Lines |Uncovered Lines |
--------------|----------|----------|----------|----------|----------------|
 parts/       |    90.48 |    58.06 |      100 |      100 |                |
  ListView.js |    90.48 |    58.06 |      100 |      100 |                |
--------------|----------|----------|----------|----------|----------------|
All files     |    90.48 |    58.06 |      100 |      100 |                |
--------------|----------|----------|----------|----------|----------------|
```

以下、設定方法。

## 使用モジュール
```
"babel-core": "^6.3.26",
"babel-loader": "^6.2.0",
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"chai": "^3.4.1",
"istanbul-instrumenter-loader": "^0.1.3",
"karma-coverage": "^0.5.3",
"karma-mocha": "^0.2.1",
"karma-mocha-reporter": "^1.1.4",
"karma-phantomjs-launcher": "^0.2.2",
"karma-phantomjs-shim": "^1.2.0",
"karma-sourcemap-loader": "^0.3.6",
"karma-webpack": "^1.7.0",
"mocha": "^2.3.4",
"phantomjs": "^1.9.19",
"react-addons-test-utils": "^0.14.5",
"webpack": "^1.12.9"
```
多い。。。

## 設定ファイル
src/以下にテスト対象ファイル
test/以下にテストファイルを置いておきます。
テストファイルの名前は、`*.spec.js`で揃えておきます。
### karma.conf.js
```
module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['phantomjs-shim', 'mocha'],
    files: [
      'test/**/*\.spec\.js'
    ],
    exclude: [
      '**/*\.swp'
    ],
    plugins: [
      'karma-phantomjs-launcher',
      'karma-phantomjs-shim',
      'karma-mocha',
      'karma-sourcemap-loader',
      'karma-webpack',
      'karma-coverage',
      'karma-mocha-reporter'
    ],
    preprocessors: {
      'test/**/*\.spec\.js': ['webpack', 'sourcemap']
    },
    // webpack設定
    webpack: {
      devtool: 'inline-source-map',
      module: {
        loaders: [
          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules\//
          }
        ],
        postLoaders: [
          {
            test: /\.js$/,
            exclude: /(test|node_modules)\//,
            loader: 'istanbul-instrumenter'
          }
        ]
      }
    },
    webpackServer: {
      noInfo: true
    },
    // mochaの実行結果とカバレッジを出力
    reporters: ['mocha', 'coverage'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    // PhantomJS上でテスト実行
    browsers: ['PhantomJS'],
    singleRun: false,
    concurrency: Infinity,
    // カバレッジ出力形式
    coverageReporter: {
      dir: 'coverage/',
      reporters: [
        { type: 'html' },
        { type: 'text' }
      ]
    }
  })
}
```
### .babelrc
```
{
  "presets": [
    "es2015",
    "react"
  ]
}
```

## テストサンプル
### テスト対象(src/components/parts/ListView.js)
```
import React, { Component } from 'react'

export default class ListView extends Component {
  constructor(props) {
    super(props)
  }

  render() {
    return (
      <div>
        <image src={this.props.imageUrl}></image>
        <span>{this.props.text}</span>
      </div>
    )
  }
}
```
### テスト(test/components/parts/ListView.spec.js)
```
import React from 'react'
import ReactTestUtils from 'react-addons-test-utils'
import { expect } from 'chai'

import ListView from '../../../src/components/parts/ListView'

describe('ListView', () => {
  it('propsが正しく設定できる', () => {
    let component = ReactTestUtils.renderIntoDocument(<ListView imageUrl="http://example.com/" text="sample" />)

    expect("http://example.com/").to.equal(component.props.imageUrl)
    expect("sample").to.equal(component.props.text)
  })
})
```

## テスト出力結果
```
START:
  ListView
    ✔ propsが正しく設定できる

Finished in 0.017 secs / 0.008 secs

SUMMARY:
✔ 1 test completed
--------------|----------|----------|----------|----------|----------------|
File          |  % Stmts | % Branch |  % Funcs |  % Lines |Uncovered Lines |
--------------|----------|----------|----------|----------|----------------|
 parts/       |    90.48 |    58.06 |      100 |      100 |                |
  ListView.js |    90.48 |    58.06 |      100 |      100 |                |
--------------|----------|----------|----------|----------|----------------|
All files     |    90.48 |    58.06 |      100 |      100 |                |
--------------|----------|----------|----------|----------|----------------|
```

## まとめ
テストもできてカバレッジも取れて幸せです。