メインコンテンツへスキップ
バージョン: 29.7

React Native アプリのテスト

非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

Facebookでは、Jestを使用してReact Nativeアプリケーションのテストを行っています。

実際のReact Nativeアプリのテスト事例を深く理解するには、以下のシリーズ記事をご覧ください: Part 1: Jest – スナップショットテストの実践Part 2: Jest – アクションとリデューサーのReduxスナップショット

セットアップ

react-nativeバージョン0.38以降では、react-native initを実行するとデフォルトでJestのセットアップが含まれます。以下の設定が自動的にpackage.jsonファイルに追加されます:

{
"scripts": {
"test": "jest"
},
"jest": {
"preset": "react-native"
}
}

yarn testを実行してJestでテストを行います。

ヒント

react-nativeアプリケーションをアップグレードしていて、以前jest-react-nativeプリセットを使用していた場合は、package.jsonファイルからその依存関係を削除し、プリセットをreact-nativeに変更してください。

スナップショットテスト

いくつかのビューとテキストコンポーネント、スタイルを持つ小さな紹介コンポーネントのスナップショットテストを作成してみましょう:

Intro.js
import React, {Component} from 'react';
import {StyleSheet, Text, View} from 'react-native';

class Intro extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>
This is a React Native snapshot test.
</Text>
</View>
);
}
}

const styles = StyleSheet.create({
container: {
alignItems: 'center',
backgroundColor: '#F5FCFF',
flex: 1,
justifyContent: 'center',
},
instructions: {
color: '#333333',
marginBottom: 5,
textAlign: 'center',
},
welcome: {
fontSize: 20,
margin: 10,
textAlign: 'center',
},
});

export default Intro;

ReactのテストレンダラーとJestのスナップショット機能を使用して、コンポーネントを操作し、レンダリングされた出力をキャプチャしてスナップショットファイルを作成します:

__tests__/Intro-test.js
import React from 'react';
import renderer from 'react-test-renderer';
import Intro from '../Intro';

test('renders correctly', () => {
const tree = renderer.create(<Intro />).toJSON();
expect(tree).toMatchSnapshot();
});

yarn testまたはjestを実行すると、次のような出力ファイルが生成されます:

__tests__/__snapshots__/Intro-test.js.snap
exports[`Intro renders correctly 1`] = `
<View
style={
Object {
"alignItems": "center",
"backgroundColor": "#F5FCFF",
"flex": 1,
"justifyContent": "center",
}
}>
<Text
style={
Object {
"fontSize": 20,
"margin": 10,
"textAlign": "center",
}
}>
Welcome to React Native!
</Text>
<Text
style={
Object {
"color": "#333333",
"marginBottom": 5,
"textAlign": "center",
}
}>
This is a React Native snapshot test.
</Text>
</View>
`;

次回テストを実行すると、レンダリングされた出力が以前作成したスナップショットと比較されます。スナップショットはコード変更とともにコミットする必要があります。スナップショットテストが失敗した場合、その変更が意図したものかどうかを確認してください。変更が予期されている場合は、jest -uでJestを実行して既存のスナップショットを上書きできます。

この例のコードはexamples/react-nativeで参照できます。

プリセット設定

このプリセットは環境を設定し、Facebookで有用とわかった方法に基づいた強い意見を持っています。すべての設定オプションは、プリセットを使用しない場合と同様に上書きしてカスタマイズできます。

環境

react-nativeにはJestプリセットが同梱されているため、package.jsonjest.presetフィールドはreact-nativeを指すようにしてください。このプリセットはReact Nativeアプリの環境を模倣するNode環境です。DOMやブラウザAPIを読み込まないため、Jestの起動時間が大幅に短縮されます。

transformIgnorePatternsのカスタマイズ

transformIgnorePatternsオプションは、Babelで変換するファイルを指定するために使用できます。多くのreact-native npmモジュールは、残念ながら公開前にソースコードを事前コンパイルしていません。

デフォルトではjest-react-nativeプリセットは、プロジェクト自身のソースファイルとreact-nativeのみを処理します。変換が必要なnpm依存関係がある場合は、react-native以外のモジュールをグループ化して|演算子で区切ることでこの設定をカスタマイズできます:

{
"transformIgnorePatterns": ["node_modules/(?!((@)?react-native|my-project)/)"]
}

このようなツールでどのパスが一致するか(つまり変換から除外されるか)をテストできます。

transformIgnorePatternsは、パスが提供されたいずれかのパターンに一致する場合、ファイルを変換から除外します。注意せずに複数のパターンに分割すると、意図しない結果になる可能性があります。以下の例では、foobarの除外(否定先読みアサーションとも呼ばれる)が互いに打ち消し合います:

{
"transformIgnorePatterns": ["node_modules/(?!foo/)", "node_modules/(?!bar/)"] // not what you want
}

setupFiles

すべてのテストファイルに追加設定を提供したい場合、setupFiles設定オプションを使用してセットアップスクリプトを指定できます。

moduleNameMapper

moduleNameMapper はモジュールパスを別のモジュールにマッピングするために使用できます。デフォルトではプリセットがすべての画像をスタブモジュールにマッピングしますが、モジュールが見つからない場合にこの設定オプションが役立ちます:

{
"moduleNameMapper": {
"my-module.js": "<rootDir>/path/to/my-module.js"
}
}

ヒント

jest.mock を使用したネイティブモジュールのモック

react-native に組み込まれた Jest プリセットには、React Native リポジトリに適用されるデフォルトのモックがいくつか含まれています。ただし、一部の React Native コンポーネントやサードパーティコンポーネントはレンダリングにネイティブコードに依存しています。そのような場合、Jest の手動モックシステムが基盤となる実装をモックするのに役立ちます。

例えば、コードが react-native-video というサードパーティのネイティブ動画コンポーネントに依存している場合、次のような手動モックでスタブアウトできます:

jest.mock('react-native-video', () => 'Video');

これによりスナップショット出力でコンポーネントが <Video {...props} /> としてレンダリングされ、すべての props が表示されます。Enzyme と React 16 を使用したモックのスナップショットテストに関する注意点も参照してください。

より複雑な手動モックが必要な場合もあります。例えばネイティブコンポーネントの prop types や静的フィールドをモックに転送したい場合、jest-react-native のこのヘルパーを使用してモックから別の React コンポーネントを返せます:

jest.mock('path/to/MyNativeComponent', () => {
const mockComponent = require('react-native/jest/mockComponent');
return mockComponent('path/to/MyNativeComponent');
});

あるいは独自の手動モックを作成したい場合は、次のような方法があります:

jest.mock('Text', () => {
const RealComponent = jest.requireActual('Text');
const React = require('react');
class Text extends React.Component {
render() {
return React.createElement('Text', this.props, this.props.children);
}
}
Text.propTypes = RealComponent.propTypes;
return Text;
});

React コンポーネントではないネイティブモジュールをモックしたい場合もありますが、同じ手法が適用できます。実機で React Native アプリを実行する際にネイティブモジュールのソースコードを調査してログに記録し、実際のモジュールをモデルにした手動モックを作成することをお勧めします。

同じモジュールを繰り返しモックする場合は、これらのモックを別ファイルで定義して setupFiles リストに追加することを推奨します。