Jest + React Testing Libraryのテスト方針を考える
自身のプロジェクトで Jest を使っているがごちゃごちゃになってきているためきちんとテスト方針を決めたい。情報収集する
どういった実装をテストすべきなのか
- 個々の小さなコンポーネントをテストするより個々のコンポーネントが連携して動作するようなコンポーネントをテストすべき
- 個々のコンポーネントが連携して動作するようなコンポーネントとは、Atomic Design でいう pages や templates ?
- ユーザーが操作する部分のテストをすべき
- 実装の詳細はテストすべきでない
- リファクタリングで壊れてしまうため
自分の経験的にお勧め
- ロジック周りは網羅的にテストしたい
- そのため複雑なロジックは custom hooks 切り出し、網羅的にテストするのが良かった
1.「実装の詳細」をテストしない
「実装の詳細」を操作するようなテストを書いてはいけません。なぜならそれは「壊れるべきでないときに壊れるテスト」と「壊れるべきときに壊れないテスト」の両方に繋がってしまうからです。
「壊れるべきでないときに壊れるテスト」
実装の詳細をテストしているということは、その実装の詳細部分を変更するとテストが壊れるということです。つまりリファクタで簡単に壊れまくります。
「壊れるべきときに壊れないテスト」
しかし、「実装の詳細」に集中した粒度の小さいテスト(ユニットテストなど)しか行っていないと、各単体のコンポーネントや機能粒度ごとの挙動しか保証できず、コンポーネントや機能同士が連携したときの挙動を担保することができません。
そのため、実装の詳細のテスト(ユニットテストなど)だけだと、実際のアプリの「全体が連携したときの挙動」は壊れているのに、テストが間違って通ってしまうことがあります。
実装の詳細をテストしないためのポイント
「ユーザーから見えるもの」という視点でテストする。「ユーザーから見えないもの」はテストしない。
テストで直接Component内のStateやメソッドをいじらない。
ユニットテストではなく、インテグレーションテストを最も書くようにする。
EnzymeのShallow Renderingは使わないようにする。
Snapshotテストをむやみに使わない
他の方針
- 外部システムに依存するテストはしない
- 「モック」はできるかぎり少なくする
- 「コードカバレッジ」より「ユースケースカバレッジ」を意識する
ダメ絶対なこと
CI実行時間が長い
CIを早くする方法は色々ある
並列実行(ワーカーレベル)
並行実行(ジョブレベル)
ランナーを使い分ける
jest では並行実行(ジョブレベル)を導入するとテストファイル数で並行に実行するようになるため
テストファイルは機能ごとなど分割して行ったほうが良さそう
Flaky Test (成功失敗が安定しないテスト)
割れ窓化、本来テストで発見すべき不具合を見逃すことにつながる
実装のコツ
act と await の使い分け