# 通知設計書 5-テスト結果通知

## 概要

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

### 本通知の処理概要

テスト結果通知は、個別のテストファイルの実行が完了した際にコンソールへ結果を出力する機能である。DefaultReporter.onTestResultメソッドで実行され、PASS/FAILステータス、実行時間、コンソール出力（console.log等）を表示する。

**業務上の目的・背景**：開発者が各テストファイルの実行結果をリアルタイムで把握できるようにする。テストが成功したか失敗したかを即座に視覚的に確認でき、失敗時はエラー情報の確認へスムーズに移行できる。また、テスト内でのconsole.log出力も適切にバッファリングされて表示される。

**通知の送信タイミング**：各テストファイルの実行が完了した時点（onTestResultイベント）で即座に実行される。スキップされたテストの場合は出力がスキップされる。

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

**通知内容の概要**：「PASS」または「FAIL」ステータスラベル、テストファイルパス、実行時間（遅いテストの場合）、メモリ使用量（設定時）、テスト内のコンソール出力が表示される。

**期待されるアクション**：開発者はテスト結果を確認し、PASSの場合は次のテストを待ち、FAILの場合はエラー内容を確認して修正作業に移る。

## 通知種別

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

## 送信仕様

### 基本情報

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

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

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

## 通知テンプレート

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

| 項目 | 内容 |
|-----|------|
| 出力先 | process.stderr |
| 成功ステータスラベル | `PASS`（緑色背景・太字・反転） |
| 失敗ステータスラベル | `FAIL`（赤色背景・太字・反転） |
| ファイルパス | 相対パス形式で表示 |

### 本文テンプレート

成功時:
```
 PASS  {projectDisplayName} {testPath}
```

失敗時:
```
 FAIL  {projectDisplayName} {testPath}
```

実行時間が遅い場合:
```
 PASS  {testPath} ({runTime}s)
```

コンソール出力がある場合:
```
 PASS  {testPath}
  ● Console

    {consoleOutput}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| testPath | テストファイルのパス | TestResult.testFilePath | Yes |
| projectDisplayName | プロジェクト表示名 | ProjectConfig.displayName | No |
| runTime | 実行時間（秒） | TestResult.perfStats.runtime / 1000 | No（遅い場合のみ） |
| memoryUsage | メモリ使用量（MB） | TestResult.memoryUsage | No（設定時のみ） |
| consoleOutput | コンソール出力 | TestResult.console | No（出力がある場合のみ） |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| イベント | onTestResult | testResult.skipped !== true | テストファイル実行完了時に発火 |

### 送信条件詳細

onTestResultイベントが発火し、かつテストがスキップされていない場合に実行される。

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| testResult.skipped === true | テストがスキップされた場合は出力しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[テストファイル実行完了] --> B[onTestResult発火]
    B --> C[testFinished呼び出し]
    C --> D{skipped?}
    D -->|Yes| Z[終了]
    D -->|No| E[printTestFileHeader呼び出し]
    E --> F[リトライエラー出力]
    F --> G[getResultHeader呼び出し]
    G --> H{console出力あり?}
    H -->|Yes| I[getConsoleOutput呼び出し]
    H -->|No| J[printTestFileFailureMessage呼び出し]
    I --> J
    J --> K[forceFlushBufferedOutput呼び出し]
    K --> Z
```

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

### 参照テーブル一覧

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

| データソース | 用途 | 備考 |
|-----------|------|------|
| Test | テスト情報 | onTestResult引数として渡される |
| TestResult | テスト実行結果 | onTestResult引数として渡される |
| AggregatedResult | 集計結果 | onTestResult引数として渡される |
| ProjectConfig | プロジェクト設定 | Test.context.configから取得 |
| GlobalConfig | グローバル設定 | コンストラクタで渡される |

### 参照項目詳細

#### TestResult

| 参照項目 | 用途 | 取得条件 |
|--------|------|---------|
| testFilePath | テストファイルパス | なし |
| skipped | スキップ判定 | なし |
| numFailingTests | 失敗判定 | なし |
| testExecError | 実行エラー判定 | なし |
| perfStats.slow | 遅いテスト判定 | なし |
| perfStats.runtime | 実行時間 | perfStats.slow === true の場合 |
| memoryUsage | メモリ使用量 | 設定されている場合 |
| console | コンソール出力 | 出力がある場合 |
| testResults | 個別テスト結果 | リトライエラー取得用 |
| failureMessage | 失敗メッセージ | 失敗時 |
| snapshot | スナップショット情報 | なし |

### 更新テーブル一覧

| データソース | 操作 | 概要 |
|-----------|------|------|
| Status | UPDATE | testFinishedで状態更新 |
| CurrentTestList | DELETE | 完了したテストをリストから削除 |

## エラー処理

### エラーケース一覧

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

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（テストファイル実行完了時に即座に出力）

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

- コンソール出力のみのため、外部への情報漏洩リスクはない
- テスト内のconsole.log出力がそのまま表示されるため、機密情報をログ出力しないよう注意が必要
- ローカル環境でのみ表示される

## 備考

- `TITLE_BULLET = chalk.bold('\u25CF ')`（●）がコンソールセクションのマーカーとして使用される
- `getConsoleOutput`は`@jest/console`パッケージから提供される
- `forceFlushBufferedOutput`によりバッファリングされた出力が即座にフラッシュされる
- `getResultHeader`は失敗テスト数またはtestExecErrorの有無でPASS/FAILを判定
- 遅いテスト（perfStats.slow === true）の場合は実行時間が赤色で強調表示される

---

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

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

### 推奨読解順序

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.ts | `packages/jest-reporters/src/types.ts` | Reporterインターフェースのメソッド定義を確認 |
| 1-2 | TestResult型 | `packages/jest-test-result` | TestResult型の構造を確認 |

**読解のコツ**: TestResultには多くのプロパティがあるが、この通知で重要なのはtestFilePath、skipped、numFailingTests、console、failureMessage。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DefaultReporter.ts | `packages/jest-reporters/src/DefaultReporter.ts` | onTestResultメソッドが通知の起点 |

**主要処理フロー**:
1. **170-189行目**: `onTestResult`メソッドの実装
2. **175行目**: `testFinished`呼び出し
3. **176行目**: `skipped`チェック
4. **177-181行目**: `printTestFileHeader`呼び出し
5. **182-186行目**: `printTestFileFailureMessage`呼び出し
6. **188行目**: `forceFlushBufferedOutput`呼び出し

#### Step 3: ヘッダー出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DefaultReporter.ts | `packages/jest-reporters/src/DefaultReporter.ts` | printTestFileHeaderメソッド（199-235行目） |
| 3-2 | getResultHeader.ts | `packages/jest-reporters/src/getResultHeader.ts` | ステータスラベル生成 |

**主要処理フロー**:
- **205-227行目**: リトライエラーの出力処理
- **229行目**: `getResultHeader`でPASS/FAILヘッダー生成
- **230-234行目**: コンソール出力がある場合の処理

#### Step 4: 失敗メッセージ出力を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | DefaultReporter.ts | `packages/jest-reporters/src/DefaultReporter.ts` | printTestFileFailureMessageメソッド（237-248行目） |
| 4-2 | getSnapshotStatus.ts | `packages/jest-reporters/src/getSnapshotStatus.ts` | スナップショットステータス生成 |

**主要処理フロー**:
- **242-244行目**: `failureMessage`がある場合はログ出力
- **245-247行目**: スナップショットステータスの出力

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

```
jest-core/runJest
    │
    ├─ ReporterDispatcher.onTestResult()
    │      │
    │      └─ DefaultReporter.onTestResult()
    │             │
    │             ├─ testFinished()
    │             │      └─ Status.testFinished()
    │             │
    │             ├─ [!skipped] printTestFileHeader()
    │             │      │
    │             │      ├─ [リトライエラー] separateMessageFromStack()
    │             │      │                   formatStackTrace()
    │             │      │
    │             │      ├─ getResultHeader()
    │             │      │      ├─ formatTestPath()
    │             │      │      └─ printDisplayName()
    │             │      │
    │             │      └─ [console出力あり] getConsoleOutput()
    │             │
    │             ├─ [!skipped] printTestFileFailureMessage()
    │             │      │
    │             │      ├─ [failureMessage] log()
    │             │      │
    │             │      └─ getSnapshotStatus()
    │             │
    │             └─ forceFlushBufferedOutput()
```

### データフロー図

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

Test ───────────────────▶ DefaultReporter.onTestResult()
  path                          │
  context.config                │
                                │
TestResult ─────────────────────┤
  testFilePath                  │
  skipped                       ├─▶ testFinished()
  numFailingTests               │
  testExecError                 │
  perfStats                     ├─▶ printTestFileHeader()
  memoryUsage                   │       │
  console                       │       ├─▶ getResultHeader() ──▶ "PASS/FAIL path"
  testResults                   │       │
  failureMessage                │       └─▶ getConsoleOutput() ▶ "● Console\n..."
  snapshot                      │
                                ├─▶ printTestFileFailureMessage()
                                │       │
                                │       ├─▶ failureMessage ──▶ stderr
                                │       │
                                │       └─▶ getSnapshotStatus()
                                │
                                └─▶ forceFlushBufferedOutput()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| DefaultReporter.ts | `packages/jest-reporters/src/DefaultReporter.ts` | ソース | onTestResult実装 |
| getResultHeader.ts | `packages/jest-reporters/src/getResultHeader.ts` | ソース | PASS/FAILヘッダー生成 |
| getSnapshotStatus.ts | `packages/jest-reporters/src/getSnapshotStatus.ts` | ソース | スナップショットステータス |
| Status.ts | `packages/jest-reporters/src/Status.ts` | ソース | testFinished処理 |
| BaseReporter.ts | `packages/jest-reporters/src/BaseReporter.ts` | ソース | log()メソッド |
| formatTestPath.ts | `packages/jest-reporters/src/formatTestPath.ts` | ソース | パスフォーマット |
| printDisplayName.ts | `packages/jest-reporters/src/printDisplayName.ts` | ソース | プロジェクト名表示 |
| getConsoleOutput | `packages/jest-console` | ソース | コンソール出力フォーマット |
| jest-message-util | `packages/jest-message-util` | ソース | スタックトレースフォーマット |
