React Native - Unit Test part1 (setup ~ component) 

React Nativeでのテストは[公式のドキュメント](https://facebook.github.io/react-native/docs/testing.html#content)でも述べられてます。テストはやや貧弱なイメージがあります。Xcodeだと2015年のキーノートで発表されたUI Testを利用が難しかったりします。

*またAndroid用のIntegration環境がドキュメントにないので、Androidで結合テストは現時点では外部モジュールに頼る必要がります。*

**方針として、ロジックとコンポーンネントを切り離し、ロジックをしっかりテストしていくことが良いかと思います。**


# Unit Test on React Native

Unitテストは基本的にJestを使ってテストしていきます。


## Jest設定方法

ドキュメント通りにpackage.jsonに下記を設定。

```
...
"scripts": {
  ...
  "test": "jest"
},
...
"jest": {
  "scriptPreprocessor": "node_modules/react-native/jestSupport/preprocessor.js",
  "setupEnvScriptFile": "node_modules/react-native/jestSupport/env.js",
  "testPathIgnorePatterns": [
    "/node_modules/",
    "packager/react-packager/src/Activity/"
  ],
  "testFileExtensions": [
    "js"
  ],
  "unmockedModulePathPatterns": [
    "promise",
    "source-map"
  ]
},
...
```

## 実行方法

`__tests__`と`__mocks__`ディレクトリを作り、

```
$ tree __*
__mocks__
└── react-native.js
__tests__
├── actions-test.js
├── component-test.js
└── reducers-test.js
```

下記コマンドでテストします。

```
 $ npm test
```

## Jest

詳しくは[Jest](https://facebook.github.io/jest/)を参照して欲しいのですが、Jestはデフォルトでmockする挙動なので、慣れが必要な気がします。コンポーネントのmockは手間がかかり大変なので、どこまでテストしていくのかははっきり考える必要があると思います。このことを考慮してプロジェクトのテスト方針をまずはじめに決める必要があると思います。

## Componentのユニットテスト

下記のコードをテストします。（コード自体は意味のないものなのはご容赦ください)

```
import React, { WebView } from 'react-native';

let terms = React.createClass({

  render(){
    return(
      <WebView
         url={this.props.url}
       />
    );
  }

});

export default terms;
```

これをテストするために`react-shallow-renderer-helpers`というモジュールをイントールします。shallow renderの説明は[Reactのshallow renderのセクション](https://facebook.github.io/react/docs/test-utils.html#shallow-rendering)を参考にしてくれれば良いと思いますが、１階層だけテストするイメージになります。

```
 $ npm install react-shallow-renderer-helpers --save
```

そして、下記のようなコードを書きます。
まず、テスト対象のWebViewはmockしない宣言をします。


```
jest.dontMock('../app/components/WebView');

const React = require('react-native');
const WebView = require('../app/components/WebView');
const shallowHelpers = require('react-shallow-renderer-helpers');

function setup(){
  let renderer = shallowHelpers.createRenderer();
  renderer.render(() => <WebView />)
  let output = renderer.getRenderOutput()
  let instance = renderer.getMountedInstance();
  return {
    output,
    instance,
    renderer
  }
}

describe('components', () => {
  describe('App', () => {
    it('has WebView', () => {
        const { output, instance } = setup();
        expect(output.type.name).toBe('WebView');
    })
  })
})
```

そして次にReactをロードするのですが、これはmock処理する必要があり、`__mock__`ディレクトリにファイルを作ります。

```
jest.dontMock('react');
var React = require('react');
var ReactNative = React;

ReactNative.StyleSheet ={
    create: function(styles) {
        return styles;
    }
};

class WebView extends React.Component {
  render(){
    return <div {...this.props}/>
  }
}

ReactNative.WebView = WebView;
ReactNative.NativeModules = {};

module.exports = ReactNative;
```

上記のように、React NativeのcomponentをReactの要素でmockしていきます。

あとは`npm test`でテストするだけです。

## Summary

今回はReact NativeのComponentのユニットテストを解説しました。モックするのがReactを使っていくので、大変というのが分かったと思います。現実問題、本当に必要な部分だけテストしていくのが良いかと思います。明日はロジックのテストをreduxのテストと絡めて説明します。