# 通知設計書 9-テスト実行サマリー通知

## 概要

本ドキュメントは、Jestテストフレームワークにおけるコンソール出力機能のうち、全テスト実行完了時に総合結果をコンソールへ出力する「テスト実行サマリー通知」の設計を記載する。

### 本通知の処理概要

テスト実行サマリー通知は、全テスト実行が完了した際に総合的な結果サマリーをコンソールへ出力する機能である。SummaryReporter.onRunCompleteメソッドで実行され、テストスイート数、テスト数、スナップショット数、実行時間、テスト対象情報を表示する。

**業務上の目的・背景**：テスト実行完了後、開発者は全体の実行結果を迅速に把握する必要がある。テスト実行サマリー通知により、成功/失敗/スキップされたテストの件数、実行時間、スナップショットの状態などが一目で確認でき、CI/CDパイプラインの結果判定やローカル開発での品質確認が効率化される。

**通知の送信タイミング**：全テスト実行が完了した時点（onRunComplete）で出力される。テストスイートが1件以上ある場合に表示される。

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

**通知内容の概要**：Test Suites（テストスイート数）、Tests（テスト数）、Snapshots（スナップショット数）、Time（実行時間）の4つのカテゴリで結果が表示される。各カテゴリで成功/失敗/スキップ等の内訳も色分けして表示される。

**期待されるアクション**：開発者は実行結果を確認し、全て成功していれば次のステップ（コミット、デプロイ等）に進む。失敗がある場合は詳細を確認して修正作業に移る。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

logメソッドを通じて標準エラー出力（process.stderr）に対して出力する。

## 通知テンプレート

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

| 項目 | 内容 |
|-----|------|
| 出力先 | process.stderr |
| 失敗 | 赤色太字 |
| スキップ | 黄色太字 |
| Todo | マゼンタ太字 |
| 成功 | 緑色太字 |

### 本文テンプレート

```
Seed:        {seed}
Test Suites: {failed} failed, {skipped} skipped, {passed} passed, {total} total
Tests:       {failed} failed, {skipped} skipped, {todo} todo, {passed} passed, {total} total
Snapshots:   {failed} failed, {obsolete} obsolete, {updated} updated, {written} written, {passed} passed, {total} total
Time:        {runTime}s, estimated {estimatedTime}s
████████████████████████████████████████
Ran all test suites matching {pattern}.
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| seed | ランダムシード値 | GlobalConfig.seed | No（showSeed時のみ） |
| suitesFailed | 失敗テストスイート数 | AggregatedResult.numFailedTestSuites | No |
| suitesPassed | 成功テストスイート数 | AggregatedResult.numPassedTestSuites | No |
| suitesPending | スキップテストスイート数 | AggregatedResult.numPendingTestSuites | No |
| suitesTotal | 総テストスイート数 | AggregatedResult.numTotalTestSuites | Yes |
| testsFailed | 失敗テスト数 | AggregatedResult.numFailedTests | No |
| testsPassed | 成功テスト数 | AggregatedResult.numPassedTests | No |
| testsPending | スキップテスト数 | AggregatedResult.numPendingTests | No |
| testsTodo | Todoテスト数 | AggregatedResult.numTodoTests | No |
| testsTotal | 総テスト数 | AggregatedResult.numTotalTests | Yes |
| runTime | 実行時間（秒） | (Date.now() - startTime) / 1000 | Yes |
| estimatedTime | 推定時間 | ReporterOnStartOptions.estimatedTime | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| イベント | onRunComplete | numTotalTestSuites > 0 | 全テスト完了時に発火 |

### 送信条件詳細

numTotalTestSuitesが0より大きい場合に出力される。

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| numTotalTestSuites === 0 | テストスイートが1件もない場合 |
| globalConfig.silent === true | silentモードの場合、一部メッセージが抑止される |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[onRunComplete発火] --> B{numTotalTestSuites > 0?}
    B -->|No| Z[終了]
    B -->|Yes| C{verboseでない かつ 最終テスト成功?}
    C -->|Yes| D[空行出力]
    C -->|No| E[_printSummary呼び出し]
    D --> E
    E --> F[_printSnapshotSummary呼び出し]
    F --> G[getSummary呼び出し]
    G --> H{silentモード?}
    H -->|Yes| I[サマリーのみ出力]
    H -->|No| J{wasInterrupted?}
    J -->|Yes| K[中断メッセージ追加]
    J -->|No| L[_getTestSummary追加]
    K --> M[log出力]
    L --> M
    I --> M
    M --> Z
```

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

### 参照テーブル一覧

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

| データソース | 用途 | 備考 |
|-----------|------|------|
| AggregatedResult | 集計結果 | onRunComplete引数から取得 |
| GlobalConfig | グローバル設定 | コンストラクタで渡される |
| TestContext | テストコンテキスト | プロジェクト数の取得 |

### 参照項目詳細

#### AggregatedResult

| 参照項目 | 用途 | 取得条件 |
|--------|------|---------|
| numTotalTestSuites | 出力条件判定・表示 | なし |
| numFailedTestSuites | 失敗スイート数表示 | なし |
| numPassedTestSuites | 成功スイート数表示 | なし |
| numPendingTestSuites | スキップスイート数表示 | なし |
| numTotalTests | 総テスト数表示 | なし |
| numFailedTests | 失敗テスト数表示 | なし |
| numPassedTests | 成功テスト数表示 | なし |
| numPendingTests | スキップテスト数表示 | なし |
| numTodoTests | Todoテスト数表示 | なし |
| startTime | 実行時間計算 | なし |
| wasInterrupted | 中断判定 | なし |
| snapshot | スナップショット情報 | なし |
| testResults | 最終テスト結果取得 | なし |

#### GlobalConfig

| 参照項目 | 用途 | 取得条件 |
|--------|------|---------|
| verbose | 空行出力判定 | なし |
| silent | サマリー詳細出力判定 | なし |
| seed | シード値表示 | showSeed時 |
| showSeed | シード値表示判定 | なし |
| testPathPatterns | テスト対象情報表示 | なし |
| testNamePattern | テスト名パターン表示 | なし |
| onlyChanged | 変更ファイル関連表示 | なし |
| runTestsByPath | パス指定実行表示 | なし |
| findRelatedTests | 関連テスト表示 | なし |
| nonFlagArgs | 引数表示 | runTestsByPath時 |

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| なし | onRunCompleteは安全に実行される | - |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

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

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

- コンソール出力のみのため、外部への情報漏洩リスクはない
- テストパスパターンが表示される場合がある
- ローカル環境でのみ表示される

## 備考

- `getSummary`関数は`packages/jest-reporters/src/getSummary.ts`で定義
- 実行時間が推定時間を1秒以上超える場合は黄色で強調表示
- プログレスバーは推定時間が2秒以上かつ実行中の場合のみ表示
- `PROGRESS_BAR_WIDTH = 40`で幅が固定
- 緑色（█）が完了部分、白色（█）が残り部分を表す
- `_getTestSummary`でテスト対象の情報（パターン、プロジェクト数等）を生成

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.ts | `packages/jest-reporters/src/types.ts` | SummaryOptions型の構造を確認 |
| 1-2 | AggregatedResult型 | `packages/jest-test-result` | 集計結果の構造を確認 |

**読解のコツ**: SummaryOptionsにはcurrentTestCases、estimatedTime、width、seed、showSeedが含まれる。

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

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

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

**主要処理フロー**:
1. **101-140行目**: `onRunComplete`メソッド
2. **105行目**: `numTotalTestSuites`チェック
3. **107-117行目**: 空行出力の条件判定
4. **119行目**: `_printSummary`呼び出し
5. **120-123行目**: `_printSnapshotSummary`呼び出し
6. **125-129行目**: `getSummary`呼び出し
7. **131-136行目**: wasInterruptedまたは_getTestSummaryの追加
8. **138行目**: 最終ログ出力

#### Step 3: サマリー生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | getSummary.ts | `packages/jest-reporters/src/getSummary.ts` | サマリー文字列生成 |

**主要処理フロー**:
- **82-198行目**: `getSummary`関数
- **119-125行目**: シード値の表示（showSeed時）
- **127-135行目**: Test Suitesの生成
- **147-161行目**: Testsの生成
- **163-193行目**: Snapshotsの生成
- **195行目**: Timeの生成
- **54-80行目**: `renderTime`関数でプログレスバー付き時間表示

#### Step 4: テスト対象情報生成を理解する

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

**主要処理フロー**:
- **210-256行目**: `_getTestSummary`メソッド
- **214-222行目**: testPathPatternsの情報
- **226-232行目**: testInfo生成（パス指定、変更関連、パターン一致）
- **236-242行目**: nameInfo生成
- **244-247行目**: contextInfo生成（複数プロジェクト時）

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

```
SummaryReporter.onRunComplete()
    │
    ├─ [numTotalTestSuites > 0]
    │      │
    │      ├─ [!verbose && 最終テスト成功] log('')
    │      │
    │      ├─ _printSummary()
    │      │      └─ [失敗あり && スイート数 > 閾値]
    │      │             └─ 失敗サマリー再出力
    │      │
    │      ├─ _printSnapshotSummary()
    │      │
    │      ├─ getSummary()
    │      │      │
    │      │      ├─ [showSeed] "Seed: {seed}"
    │      │      ├─ "Test Suites: ..."
    │      │      ├─ "Tests: ..."
    │      │      ├─ "Snapshots: ..."
    │      │      └─ renderTime()
    │      │             └─ "Time: {time}" + プログレスバー
    │      │
    │      ├─ [!silent]
    │      │      ├─ [wasInterrupted] "Test run was interrupted."
    │      │      └─ [!wasInterrupted] _getTestSummary()
    │      │             └─ "Ran all test suites..."
    │      │
    │      └─ log(message)
```

### データフロー図

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

AggregatedResult ───────▶ SummaryReporter.onRunComplete()
  numTotalTestSuites            │
  numFailedTestSuites           │
  numPassedTestSuites           ├─▶ _printSummary()
  numPendingTestSuites          │       └─▶ 失敗サマリー（条件付き）
  numTotalTests                 │
  numFailedTests                ├─▶ _printSnapshotSummary()
  numPassedTests                │       └─▶ スナップショットサマリー
  numPendingTests               │
  numTodoTests                  ├─▶ getSummary()
  startTime                     │       │
  wasInterrupted                │       ├─▶ "Seed: ..."
  snapshot                      │       ├─▶ "Test Suites: ..."
  testResults                   │       ├─▶ "Tests: ..."
                                │       ├─▶ "Snapshots: ..."
GlobalConfig ───────────────────┤       └─▶ "Time: ..." + ████...
  verbose                       │
  silent                        ├─▶ _getTestSummary()
  seed                          │       └─▶ "Ran all test suites..."
  showSeed                      │
  testPathPatterns              │
  testNamePattern               │
  onlyChanged                   │
                                └─▶ log() ───▶ stderr
TestContext ────────────────────┤
  (size)                        └─▶ プロジェクト数情報
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SummaryReporter.ts | `packages/jest-reporters/src/SummaryReporter.ts` | ソース | onRunComplete実装 |
| getSummary.ts | `packages/jest-reporters/src/getSummary.ts` | ソース | サマリー文字列生成 |
| getResultHeader.ts | `packages/jest-reporters/src/getResultHeader.ts` | ソース | 失敗サマリーのヘッダー |
| BaseReporter.ts | `packages/jest-reporters/src/BaseReporter.ts` | ソース | log()メソッド、onRunStart |
| types.ts | `packages/jest-reporters/src/types.ts` | ソース | SummaryOptions型 |
