# 通知設計書 11-詳細テスト結果通知

## 概要

本ドキュメントは、Jestテストフレームワークにおけるverboseモード時の詳細テスト結果通知機能の設計について記載する。VerboseReporterクラスによって実装され、各テストケースの成功/失敗/スキップ/todoの状態をツリー形式でコンソールに出力する。

### 本通知の処理概要

**業務上の目的・背景**：テスト実行時にverboseモードを有効にすることで、開発者は各テストケースの実行結果を詳細に確認できる。これにより、どのテストがパスし、どのテストが失敗したかを一目で把握でき、デバッグ作業の効率化に寄与する。特に大規模なテストスイートでは、個々のテストの状態を追跡することが重要であり、verboseモードはこのニーズに応える。

**通知の送信タイミング**：各テストファイルの実行完了時に`onTestResult`メソッドが呼び出される。テストがスキップされておらず、実行エラーが発生していない場合に、テスト結果がツリー形式で出力される。

**通知の受信者**：コンソール出力を監視している開発者。CI/CD環境ではログ収集システムを通じて開発チーム全体に共有される。

**通知内容の概要**：各テストケースについて、ステータスアイコン（成功: 緑のチェック、失敗: 赤のX、pending: 黄色の丸、todo: マゼンタの丸）、テスト名、実行時間を表示する。テストはdescribeブロックの階層構造に従ってインデント付きで表示される。

**期待されるアクション**：開発者は出力を確認し、失敗したテストの修正、スキップされたテストの対応、todoテストの実装を行う。また、実行時間が長いテストについてはパフォーマンス最適化を検討する。

## 通知種別

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

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 中 |
| リトライ | なし |

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

標準出力（process.stdout）に直接出力される。verboseモード（--verbose オプションまたは設定ファイルでverbose: true）が有効な場合にのみ出力される。

## 通知テンプレート

### コンソール出力形式

| 項目 | 内容 |
|-----|------|
| 出力先 | 標準出力（stdout） |
| 形式 | テキスト（ANSIカラーコード付き） |

### 本文テンプレート

```
  {describeブロック名}
    {ステータスアイコン} {テスト名} ({実行時間})
    {ステータスアイコン} {テスト名} ({実行時間})
  {ネストしたdescribeブロック名}
    {ステータスアイコン} {テスト名} ({実行時間})
```

### ステータスアイコン一覧

| ステータス | アイコン | 色 |
|----------|--------|-----|
| passed | ICONS.success (チェックマーク) | 緑 |
| failed | ICONS.failed (X) | 赤 |
| pending | ICONS.pending (丸) | 黄 |
| todo | ICONS.todo (丸) | マゼンタ |

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| testResults | テスト結果の配列 | TestResult.testResults | Yes |
| title | テストケース名 | AssertionResult.title | Yes |
| status | テストステータス | AssertionResult.status | Yes |
| duration | 実行時間（ミリ秒） | AssertionResult.duration | No |
| ancestorTitles | 親describeブロック名の配列 | AssertionResult.ancestorTitles | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| テスト完了 | onTestResult呼び出し | verboseモード有効 & テストがスキップされていない & 実行エラーなし | VerboseReporter.onTestResult()で実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| verboseモード無効 | --verbose オプションが指定されていない場合 |
| テストスキップ | result.skipped が true の場合 |
| 実行エラー発生 | result.testExecError が存在する場合 |
| expandモード無効時のpending/todo | _globalConfig.expand が false の場合、pending/todoテストはサマリー表示 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[onTestResult呼び出し] --> B{result.skipped?}
    B -->|Yes| Z[終了]
    B -->|No| C[printTestFileHeader出力]
    C --> D{testExecError?}
    D -->|Yes| E[printTestFileFailureMessage]
    D -->|No| F[_logTestResults呼び出し]
    F --> G[groupTestsBySuites]
    G --> H[_logSuite再帰処理]
    H --> I[_logTests]
    I --> J{expandモード?}
    J -->|Yes| K[全テスト個別出力]
    J -->|No| L[passed/failed個別 + pending/todoサマリー]
    K --> M[_logLine出力]
    L --> M
    M --> E
    E --> Z
```

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

### 参照テーブル一覧

本機能はデータベースを使用しない。

### テーブル別参照項目詳細

該当なし（メモリ内のTestResult構造体を参照）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 出力エラー | stdoutへの書き込み失敗 | Node.jsの標準エラー処理に委譲 |
| duration未定義 | テスト実行時間が取得できない場合 | 実行時間を表示しない（空文字） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（同期出力） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし

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

- テスト名やエラーメッセージに機密情報が含まれる可能性があるため、CI/CD環境でのログ保持期間や公開範囲に注意が必要
- 出力内容はフィルタリングされないため、テストコード内で機密情報を直接記述しないことを推奨

## 備考

- VerboseReporterはDefaultReporterを継承している
- 出力のバッファリングは無効化されており、リアルタイムで出力される（デバッグ目的のため）
- filterTestResultsメソッドでpendingステータスのテストをフィルタリング可能

---

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

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

### 推奨読解順序

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

まず、テスト結果を表すデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | test-result/types.ts | `packages/jest-test-result/src/types.ts` | AssertionResult型（title, status, duration, ancestorTitles）の定義を確認 |
| 1-2 | VerboseReporter.ts | `packages/jest-reporters/src/VerboseReporter.ts` | Suite型（L54-57）の定義を確認。suites, tests, titleを持つツリー構造 |

**読解のコツ**: Suite型は再帰的なツリー構造で、describeブロックの入れ子を表現している。

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

処理の起点となるonTestResultメソッドを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | VerboseReporter.ts | `packages/jest-reporters/src/VerboseReporter.ts` | onTestResultメソッド（L75-97）がエントリーポイント |

**主要処理フロー**:
1. **L80**: super.testFinished()で基底クラスの終了処理
2. **L81-82**: result.skippedでなければprintTestFileHeader出力
3. **L87-89**: testExecErrorがなければ_logTestResultsを呼び出し
4. **L90-94**: printTestFileFailureMessageで失敗メッセージ出力
5. **L96**: forceFlushBufferedOutputでバッファフラッシュ

#### Step 3: テスト結果のグルーピング処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | VerboseReporter.ts | `packages/jest-reporters/src/VerboseReporter.ts` | groupTestsBySuites静的メソッド（L54-73）でテストをdescribeブロックごとにグループ化 |

**主要処理フロー**:
- **L55**: ルートSuiteオブジェクトを作成
- **L56-71**: 各テスト結果についてancestorTitlesを辿り、適切なSuiteに配置
- **L62-67**: 既存のSuiteがなければ新規作成してpush

#### Step 4: ツリー形式での出力処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | VerboseReporter.ts | `packages/jest-reporters/src/VerboseReporter.ts` | _logSuite（L104-114）が再帰的にスイートを出力 |
| 4-2 | VerboseReporter.ts | `packages/jest-reporters/src/VerboseReporter.ts` | _logTests（L136-167）がテスト結果を出力 |
| 4-3 | VerboseReporter.ts | `packages/jest-reporters/src/VerboseReporter.ts` | _logTest（L128-134）が個別テストを出力 |

**主要処理フロー**:
- **L105-107**: スイートタイトルをインデント付きで出力
- **L109**: 子テストを出力
- **L111-113**: 子スイートを再帰的に処理
- **L137-166**: expandモードの判定とpending/todoのグルーピング処理

#### Step 5: アイコン取得処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | VerboseReporter.ts | `packages/jest-reporters/src/VerboseReporter.ts` | _getIcon（L116-126）でステータスに応じたアイコンを返す |

**主要処理フロー**:
- **L117-118**: failed → 赤のICONS.failed
- **L119-120**: pending → 黄のICONS.pending
- **L121-122**: todo → マゼンタのICONS.todo
- **L123-124**: その他（passed） → 緑のICONS.success

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

```
VerboseReporter.onTestResult (L75)
    │
    ├─ super.testFinished (L80)
    │
    ├─ printTestFileHeader (L82-86)
    │
    ├─ _logTestResults (L88)
    │      │
    │      ├─ groupTestsBySuites [static] (L54)
    │      │
    │      └─ _logSuite (L104) [再帰]
    │             │
    │             ├─ _logLine (L179)
    │             │
    │             ├─ _logTests (L136)
    │             │      │
    │             │      ├─ _logTest (L128)
    │             │      │      │
    │             │      │      ├─ _getIcon (L116)
    │             │      │      │
    │             │      │      └─ _logLine (L179)
    │             │      │
    │             │      └─ _logTodoOrPendingTest (L169)
    │             │
    │             └─ _logSuite [再帰] (L111)
    │
    ├─ printTestFileFailureMessage (L90-94)
    │
    └─ forceFlushBufferedOutput (L96)
```

### データフロー図

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

TestResult ───────────▶ groupTestsBySuites ───────────▶ Suite（ツリー構造）
  │                           │
  │ testResults               │
  │ (AssertionResult[])       ▼
  │                     _logSuite（再帰）
  │                           │
  │                           ├──▶ _logTests
  │                           │         │
  │                           │         ├──▶ _logTest ──▶ stdout
  │                           │         │
  │                           │         └──▶ _logTodoOrPendingTest ──▶ stdout
  │                           │
  │                           └──▶ _logSuite（再帰）
  │
  └─────────────────▶ this.log() ───────────────────────▶ stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| VerboseReporter.ts | `packages/jest-reporters/src/VerboseReporter.ts` | ソース | メイン実装ファイル |
| DefaultReporter.ts | `packages/jest-reporters/src/DefaultReporter.ts` | ソース | 基底クラス（printTestFileHeader等を提供） |
| BaseReporter.ts | `packages/jest-reporters/src/BaseReporter.ts` | ソース | Reporterインターフェースの基底実装 |
| types.ts | `packages/jest-test-result/src/types.ts` | 型定義 | TestResult, AssertionResult等の型定義 |
| jest-util/specialChars.ts | `packages/jest-util/src/specialChars.ts` | ソース | ICONS定数（success, failed, pending, todo） |
