React Nativeのテストコードを書くときのTips集
使っているテストフレームワーク
- jest
- jest-expo
- ts-jest
- babel-jest
- @types/jest
- @testing-library/jest-native
- @testing-library/react-native
前提
- expoを使っている(eject予定なので、そのときの移行Tipsもまとめられたらと思う)
jest.config.js
module.exports = {
preset: 'jest-expo',
setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect'],
moduleFileExtensions: ['ts', 'tsx', 'js'],
transform: {
'^.+\\.(js)$': '<rootDir>/node_modules/babel-jest',
'\\.(ts)$': 'ts-jest',
'^.+\\.tsx?$': 'babel-jest',
},
testRegex: '(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$',
testPathIgnorePatterns: ['\\.snap$', '<rootDir>/node_modules/'],
cacheDirectory: '.jest/cache',
globals: {
'ts-jest': {
tsconfig: 'tsconfig.json',
},
},
transformIgnorePatterns: [
'node_modules/(?!((jest-)?react-native|react-router-native|react-clone-referenced-element|expo(nent)?|@expo(nent)?/.*|react-navigation|以下略))',
],
};
ポイントはtransformIgnorePatterns
ここに地道に設定を足していく
あとは設定のなかでいくつかDeprecatedになるものがあり、そのへんのネット文献だと警告が出るものは修正している
良いスクラップ記載ありがとうございます!
globalsにts-jestを記載しているとdeprecatedの警告が出るので、
"\\.(ts)$": ["ts-jest", { tsconfig: "tsconfig.json" }],
この書き方の方が良いかもしれません。
各jest系パッケージのバージョン
メジャーバージョンを合わせておくほうがよさげ。
テストファイルの拡張子
基礎的なところだが、テストファイルの拡張子は.test.tsx
のようにtsxとする
コンポーネントの表示テスト
以下が例。
const component = render(<ChatMessage message={createMockMessage()} />);
expect(component.queryByText('text')).toBeTruthy();
expect(component.queryByText(LABELS.READ)).toBeNull();
expect(component.queryByA11yLabel(LABELS.DELETE_BUTTON)).toBeNull();
render
TSXコンポーネントを渡す。
queryByText
実際に表示されているテキストを検索してくれる。厳密にテストしたければもう少し工夫の余地がありそう。
ちなみにgetByTextというのもありこちらを利用しても同様の結果は得られる。しかし「表示されていないこと」をテストしたいときgetXXXを使うとそこで落ちてしまうため、現状queryをベースにテストを書いていくことが好み。
queryByA11yLabel
画像など、表示されている内容がテキストではない場合にとりあえず使っている。
元コンポーネントの方でアクセシビリティラベルを設定するとよい。
<Image
accessibilityLabel="送信された画像"
source={{ uri: props.uri }}
/>
存在しない場合はNULLが返ってくるためそれをアサートする
@testing-library/react-native 注意点
cleanup
以下を書く
afterEach(cleanup);
render
renderメソッドはitメソッド内で実行する必要がありそう。describeで実行するとUnable to find node on an unmounted component.
というエラーになった
Alertのモック
アラートが表示されることをモックでアサートしたい
spyOn
でモック関数をImplementationOnceして入れ込めばいい。引数はそのまま流す
import { Alert } from 'react-native';
const mockAlert = jest.fn();
jest.spyOn(Alert, 'alert').mockImplementationOnce((...arg) => mockAlert(...arg));
そしてテストは普通にモック関数のテストを書けばいい。以下は若干好奇心もあり書きすぎたがだいたいこんな感じで書ける
fireEvent(component.queryByA11yLabel('削除ボタン'), 'click');
expect(Alert.alert).toHaveBeenCalledTimes(1);
expect(mockAlert.mock.calls.length).toBe(1);
expect(mockAlert.mock.calls[0][0]).toBe('本当に削除しますか?');
expect(mockAlert.mock.calls[0][1]).toBe('この操作は取り消すことができません');
expect(mockAlert.mock.calls[0][2][0].text).toBe('いいえ');
expect(mockAlert.mock.calls[0][2][1].text).toBe('はい');