テストのフレーキーは状態の非独立が原因 — 現在時刻・実行順・共有 state/sequence への依存を断ち決定的にする
テスト
設計判断
信頼性
原則
テストの『通った/落ちた』を対象コードの正しさの証拠として使えるのは、その結果がコード以外の要因(実行時刻・実行順・他テストが残した状態)で変わらないときだけ。最適化するのは『同じ入力なら実行時刻・実行順に関係なく同じ結果になる独立したテスト』、避けるのは『現在時刻基準のフィクスチャ、テスト間で共有される状態、グローバルな採番への依存で、特定の時間帯・実行順でだけ落ちる(または無関係に通る)テスト』。これは『緑を額面で信じず実装を壊して落ちるか確かめる』偽陰性対策とは別の、偽の赤・非決定性の問題として扱う。
判断基準
- 現在時刻基準の相対フィクスチャは、照合の粒度(日・週・月)へ丸めた瞬間に区別が消えうる。時刻差を照合粒度より十分大きく取るか、現在時刻に依存しない固定時刻を使う。深夜帯や日付境界でだけ落ちるテストはこの型を疑う。
- 状態を持つ mock / handler / フィクスチャをテスト間で共有しない。setup の粒度(メソッド単位など)とケースの粒度がずれると、先行ケースが残した状態が後続へ漏れて順序依存になる。ケースごとに状態を作り直すか、各ケース前に明示的にリセットする。
- 既存データ件数・一覧の先頭・固定 ID の採番など、共有された環境の現在値に結果を依存させない。作成物は自分が作った対象を名指しで検証し、固定 ID の seed は採番列との衝突を避ける。
- フレーキーを『再実行で通るから』で放置しない。非決定の原因(時刻・順序・共有状態)を型として特定し、依存自体を断つ。
なぜ
非独立なテストは、コードが正しくても落ち、壊れても通りうる。どちらも結果のシグナルを無価値にし、CI の信頼とデバッグ時間を奪う。独立・決定性を設計対象にすれば、赤は必ずコードの問題を意味する。
検証
疑わしいテストを境界条件(日付が変わる時刻、逆順実行、先行ケースありの並び)で繰り返し走らせ、結果が変わらないことを確認する。時刻を境界付近に固定して再現し、修正後も同条件で安定することを見る。
根拠(synthesize 元)
- 521 相対時刻フィクスチャは日付境界で別レコードと衝突しテストをフレーキーにする
- 447 Storybook の MSW handler は story 間で状態共有される前提で設計する
- 519 固定 ID の seed データは DB sequence を進めないとテスト挿入で衝突する