# 通知設計書 10-失敗テストサマリー通知

## 概要

本ドキュメントは、Jestテストフレームワークにおけるコンソール出力機能のうち、テストスイート数が閾値を超え、かつ失敗テストがある場合に失敗テストのサマリーを再出力する「失敗テストサマリー通知」の設計を記載する。

### 本通知の処理概要

失敗テストサマリー通知は、大量のテストスイートを実行した際に、失敗テストの情報が出力ログの中で埋もれてしまうことを防ぐため、全テスト完了後に失敗テストのサマリーを再出力する機能である。SummaryReporter._printSummaryメソッドで実行される。

**業務上の目的・背景**：大規模プロジェクトでは数百〜数千のテストスイートが実行されることがある。テスト実行中に出力された失敗情報がスクロールアウトしてしまい、開発者が失敗テストを見つけるためにログを遡る必要がある。失敗テストサマリー通知により、全テスト完了後に失敗テストの一覧が再表示され、失敗箇所の特定が容易になる。

**通知の送信タイミング**：全テスト実行が完了した時点（onRunComplete → _printSummary内）で、テストスイート数が閾値（デフォルト20）を超え、かつ失敗テストがある場合に出力される。

**通知の受信者**：テストを実行した開発者のコンソール（標準エラー出力）に表示される。

**通知内容の概要**：「Summary of all failing tests」というヘッダーの下に、失敗した各テストのPASS/FAILヘッダーとfailureMessage（エラー詳細）が再出力される。

**期待されるアクション**：開発者は失敗テストの一覧を確認し、個別の失敗内容を把握して修正作業に移る。

## 通知種別

コンソール出力（標準エラー出力）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（_printSummary内で直接呼び出し） |
| 優先度 | 高 |
| リトライ | なし |

### 送信先決定ロジック

_writeメソッドを通じて標準エラー出力（process.stderr）に対して1文字ずつ出力する。これはNode.jsの終了タイミングの問題を回避するための対策である。

## 通知テンプレート

### コンソール出力の場合

| 項目 | 内容 |
|-----|------|
| 出力先 | process.stderr |
| ヘッダー | `Summary of all failing tests`（太字） |
| 各テスト | PASS/FAILヘッダー + failureMessage |

### 本文テンプレート

```
Summary of all failing tests
 FAIL  {testPath}
{failureMessage}

 FAIL  {testPath2}
{failureMessage2}

```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| testPath | テストファイルのパス | TestResult.testFilePath | Yes |
| failureMessage | 失敗メッセージ | TestResult.failureMessage | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| イベント | onRunComplete → _printSummary | 失敗あり かつ スイート数 > 閾値 | 全テスト完了時に発火 |

### 送信条件詳細

以下の全ての条件を満たす場合に出力される：
1. `failedTests + runtimeErrors > 0`（失敗テストまたはランタイムエラーあり）
2. `numTotalTestSuites > summaryThreshold`（テストスイート数が閾値超過）

閾値のデフォルト値は20で、summaryThresholdオプションで変更可能。

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 失敗テスト数 + ランタイムエラー数 === 0 | 失敗がない場合 |
| numTotalTestSuites <= summaryThreshold | テストスイート数が閾値以下の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[onRunComplete発火] --> B[_printSummary呼び出し]
    B --> C{failedTests + runtimeErrors > 0?}
    C -->|No| Z[終了]
    C -->|Yes| D{numTotalTestSuites > summaryThreshold?}
    D -->|No| Z
    D -->|Yes| E[Summary of all failing testsヘッダー出力]
    E --> F[testResultsをループ]
    F --> G{failureMessage存在?}
    G -->|No| H[次のtestResult]
    G -->|Yes| I[getResultHeader呼び出し]
    I --> J[_write でヘッダー+failureMessage出力]
    J --> H
    H --> K{次のtestResultあり?}
    K -->|Yes| F
    K -->|No| L[空行出力]
    L --> Z
```

## データベース参照・更新仕様

### 参照テーブル一覧

本通知はデータベースを使用しない。メモリ上のデータ構造からデータを取得する。

| データソース | 用途 | 備考 |
|-----------|------|------|
| AggregatedResult | 集計結果・テスト結果 | onRunComplete引数から取得 |
| GlobalConfig | グローバル設定 | getResultHeaderで使用 |
| SummaryReporterOptions | 閾値設定 | コンストラクタで渡される |

### 参照項目詳細

#### AggregatedResult

| 参照項目 | 用途 | 取得条件 |
|--------|------|---------|
| numFailedTests | 失敗判定 | なし |
| numRuntimeErrorTestSuites | 失敗判定 | なし |
| numTotalTestSuites | 閾値判定 | なし |
| testResults | 各テスト結果のループ | なし |

#### TestResult

| 参照項目 | 用途 | 取得条件 |
|--------|------|---------|
| failureMessage | 失敗メッセージ出力 | なし |
| testFilePath | ヘッダー表示 | getResultHeaderで使用 |

#### SummaryReporterOptions

| 参照項目 | 用途 | 取得条件 |
|--------|------|---------|
| summaryThreshold | 閾値（デフォルト20） | なし |

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| TypeError | summaryThresholdが数値でない | コンストラクタでバリデーションエラーをスロー |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | N/A |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（全テスト完了時に出力）

## セキュリティ考慮事項

- コンソール出力のみのため、外部への情報漏洩リスクはない
- failureMessageにはテストデータや期待値が含まれる可能性がある
- ローカル環境でのみ表示される

## 備考

- `_write`メソッドは1文字ずつ出力する。これはNode.js 0.10〜6.7+で観察された、大量出力時のプロセス終了問題への対策
- `summaryThreshold`オプションのバリデーションはコンストラクタで実施
- `getResultHeader`はPASS/FAILラベルとテストパスを含むヘッダー文字列を生成
- 空行は最後に1回だけ出力される

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、通知処理で使用されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SummaryReporter.ts | `packages/jest-reporters/src/SummaryReporter.ts` | SummaryReporterOptions型の定義（51-53行目） |

**読解のコツ**: SummaryReporterOptionsはsummaryThresholdのみを含むシンプルな型。

#### Step 2: エントリーポイントを理解する

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SummaryReporter.ts | `packages/jest-reporters/src/SummaryReporter.ts` | _printSummaryメソッド |

**主要処理フロー**:
1. **185-208行目**: `_printSummary`メソッド
2. **191-192行目**: failedTests + runtimeErrorsの計算
3. **193-196行目**: 条件判定（失敗あり かつ スイート数 > 閾値）
4. **197行目**: ヘッダー "Summary of all failing tests" 出力
5. **198-205行目**: testResultsのループ処理
6. **199行目**: failureMessageの存在チェック
7. **200-203行目**: getResultHeaderとfailureMessageの出力
8. **206行目**: 空行出力

#### Step 3: _writeメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SummaryReporter.ts | `packages/jest-reporters/src/SummaryReporter.ts` | _writeメソッド |

**主要処理フロー**:
- **87-91行目**: `_write`メソッド
- **88-90行目**: 文字列を1文字ずつprocess.stderr.writeで出力
- コメントでNode.jsの終了タイミング問題への対策であることが説明されている

#### Step 4: 閾値バリデーションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | SummaryReporter.ts | `packages/jest-reporters/src/SummaryReporter.ts` | _validateOptionsメソッド |

**主要処理フロー**:
- **73-80行目**: `_validateOptions`メソッド
- **74-79行目**: summaryThresholdが存在し、かつ数値でない場合はTypeError

### プログラム呼び出し階層図

```
SummaryReporter.onRunComplete()
    │
    └─ _printSummary()
           │
           ├─ failedTests + runtimeErrors > 0 判定
           │
           ├─ numTotalTestSuites > _summaryThreshold 判定
           │
           ├─ [条件合致]
           │      │
           │      ├─ log("Summary of all failing tests")
           │      │
           │      └─ for (testResult of testResults)
           │             │
           │             └─ [failureMessage存在]
           │                    │
           │                    ├─ getResultHeader()
           │                    │      └─ "FAIL testPath"
           │                    │
           │                    └─ _write(header + failureMessage)
           │                           │
           │                           └─ 1文字ずつ stderr.write
           │
           └─ log('')
```

### データフロー図

```
[入力]                    [処理]                         [出力]

AggregatedResult ───────▶ SummaryReporter._printSummary()
  numFailedTests                │
  numRuntimeErrorTestSuites     ├─▶ 失敗判定
  numTotalTestSuites            ├─▶ 閾値判定
  testResults[]                 │
    testFilePath                │
    failureMessage              │
                                ├─▶ [条件合致]
SummaryReporterOptions ─────────┤       │
  summaryThreshold              │       ├─▶ log("Summary...")
                                │       │
GlobalConfig ───────────────────┤       └─▶ for (testResult)
                                │              │
                                │              ├─▶ getResultHeader()
                                │              │      └─▶ "FAIL path"
                                │              │
                                │              └─▶ _write() ───▶ stderr
                                │                     └─ 1文字ずつ
                                │
                                └─▶ log('') ───▶ stderr
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SummaryReporter.ts | `packages/jest-reporters/src/SummaryReporter.ts` | ソース | _printSummary実装（185-208行目）、_write実装（87-91行目） |
| getResultHeader.ts | `packages/jest-reporters/src/getResultHeader.ts` | ソース | PASS/FAILヘッダー生成 |
| BaseReporter.ts | `packages/jest-reporters/src/BaseReporter.ts` | ソース | log()メソッド |
| TestResult型 | `packages/jest-test-result` | 型定義 | failureMessage、testFilePath |
