# E2Eテスト知識

## E2Eテストのスコープ

E2Eテストはユーザーの操作フロー全体を検証する。ユニットテストやインテグレーションテストとはスコープが異なる。

| テスト種別 | スコープ | 検証対象 |
|-----------|---------|---------|
| ユニット | 関数/クラス | ロジックの正しさ |
| インテグレーション | モジュール間結合 | データフローの正しさ |
| E2E | ユーザー操作フロー全体 | ユーザーから見た振る舞い |


## 振る舞い観測

E2Eテストはユーザーから見える振る舞いを観測する。設定値、ログ、スナップショットの確認だけでは、実際の拒否、許可、隔離、回復が起きたことを保証しない。


## 否定契約の観測

E2E で権限、実行時に選択される能力・バックエンド・オプション、設定、拒否、隔離を確認する場合、出力全体への文字列否定は証拠として弱い。
対象の行、イベント、レコード、フィールド、呼び出し引数などを取り出し、禁止値ごとに検査することで、順序、大小文字、空白、区切り、部分漏れによる見逃しを防ぐ。


## UXルートの洗い出し

E2Eテストの網羅性はユーザー操作ルートの洗い出しに依存する。ドキュメントではなくコードから起点を特定する。

### 起点の特定方法

| アプリケーション種別 | 起点の探し方 |
|-------------------|------------|
| CLI | コマンド定義、サブコマンド登録、オプション/フラグ定義をコードから抽出 |
| Web | ルーティング定義、ページコンポーネント一覧をコードから抽出 |
| API | エンドポイント定義、ルーター登録をコードから抽出 |

### 分岐パターン

各起点から分岐するルートを網羅的に列挙する。

| 分岐パターン | 例 |
|------------|-----|
| オプション/フラグの組み合わせ | `--verbose` あり/なし、`--format json` vs `--format table` |
| 状態による分岐 | 初回実行 vs 既存データあり、設定ファイルあり vs なし |
| 権限/ロール | 管理者 vs 一般ユーザー、認証済み vs 未認証 |
| 外部依存の状態 | 接続成功 vs タイムアウト、正常レスポンス vs エラーレスポンス |
| エラーリカバリー | 途中で失敗した場合の再試行、ロールバック |
| 入力バリエーション | 有効な入力、無効な入力、空入力、境界値 |


## モック境界の設計

E2Eテストでは「どこまで実物で動かし、どこからモックするか」の判断が重要。

### モック設計の原則

- テスト対象のアプリケーションコードはそのまま動かす
- 外部サービスとの境界でモックを挿入する
- モックは既存のフィクスチャ・ヘルパーのパターンに合わせる
- 新しいモック機構を導入する前に既存のものを確認する

## フレイキーテスト対策

E2Eテストは非決定的な要因で失敗しやすい。

| 原因 | 対策 |
|------|------|
| タイミング依存 | 明示的な待機条件を使う（固定 sleep ではなく状態ベースの待機） |
| ポート競合 | テストごとにランダムポートを割り当てる |
| ファイルシステムの残留 | テストごとに一時ディレクトリを作成し、終了時にクリーンアップ |
| プロセスリーク | タイムアウトと強制終了を設定する |
| 環境依存 | テスト実行に必要な前提条件を明示的にセットアップする |
| 実行順序依存 | 各テストが独立して実行できるよう、状態を初期化する |
| 既存規約から外れた timeout/cleanup | 同種 E2E の既存規約に合わせる |

```typescript
// 避ける例: 固定 sleep でタイミングを合わせる
await sleep(3000)
expect(result).toBeDefined()

// 例: 条件ベースで待機する
await waitFor(() => expect(result).toBeDefined(), { timeout: 5000 })
```

## テストケース管理

E2Eテストの網羅性を保証するため、テストケースをリストで管理する。

| 原則 | 内容 |
|------|------|
| 番号付きリスト | 各テストケースに一意の番号を付与し、実装状況を追跡する |
| 起点ごとに分類 | コマンド/ページ/エンドポイント単位でグループ化する |
| 優先度付け | ユーザー影響度 × 未テストのリスクで優先度を決定する |
| 既存テストとの突き合わせ | 新規追加前に既存テストのカバー範囲を確認する |
