# 通知設計書 14-カバレッジ閾値違反通知

## 概要

本ドキュメントは、Jestテストフレームワークにおけるカバレッジ閾値違反通知機能の設計について記載する。CoverageReporterクラスの`_checkThreshold`メソッドによって実装され、設定されたカバレッジ閾値を下回った場合にエラーメッセージを出力し、テスト失敗として扱う。

### 本通知の処理概要

**業務上の目的・背景**：コードカバレッジの閾値を設定することで、一定のテストカバレッジを維持する品質ゲートとして機能する。カバレッジが閾値を下回った場合にCI/CDパイプラインを失敗させることで、テスト不足のコードがマージされることを防ぐ。statements、branches、lines、functionsの4つの指標それぞれに閾値を設定できる。

**通知の送信タイミング**：テスト実行完了後、カバレッジレポート出力後に`_checkThreshold`メソッドが呼び出される。閾値設定（coverageThreshold）が存在する場合にのみ実行される。

**通知の受信者**：コンソールを監視している開発者。CI/CD環境ではビルド結果として開発チーム全体に通知される。

**通知内容の概要**：閾値違反が発生した場合、赤字の太字でエラーメッセージが出力される。メッセージには、どの指標（statements/branches/lines/functions）がどの閾値を下回ったかが具体的に示される。

**期待されるアクション**：開発者はカバレッジが不足している領域に対してテストを追加し、閾値をクリアするようにする。または、閾値設定を見直す。

## 通知種別

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

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（エラー扱い） |
| リトライ | なし |

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

標準出力（this.log）に直接出力される。閾値違反がある場合はエラーとしてマークされる。

## 通知テンプレート

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

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

### 本文テンプレート（パーセント閾値）

```
Jest: "{対象名}" coverage threshold for {指標} ({閾値}%) not met: {実際値}%
```

### 本文テンプレート（未カバー数閾値）

```
Jest: Uncovered count for {指標} ({実際の未カバー数}) exceeds {対象名} threshold ({閾値})
```

### エラーメッセージ例

```
Jest: "global" coverage threshold for statements (80%) not met: 65.5%
Jest: Uncovered count for branches (15) exceeds src/utils threshold (10)
Jest: Coverage data for ./src/missing.ts was not found.
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| coverageThreshold | 閾値設定オブジェクト | _globalConfig.coverageThreshold | Yes |
| actual | 実際のカバレッジ率 | actuals[key].pct | Yes |
| actualUncovered | 実際の未カバー数 | actuals[key].total - actuals[key].covered | Yes |
| threshold | 設定された閾値 | thresholds[key] | Yes |
| name | 閾値グループ名 | thresholdGroup | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| テスト完了後 | onRunComplete → _checkThreshold | coverageThreshold設定あり & 閾値違反あり | CoverageReporter._checkThreshold()で実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| coverageThreshold未設定 | 閾値設定がない場合は処理をスキップ |
| 全ての閾値をクリア | 全ての指標が閾値を満たしている場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[_checkThreshold呼び出し] --> B{coverageThreshold設定?}
    B -->|No| Z[終了]
    B -->|Yes| C[閾値グループタイプ分類]
    C --> D[ファイル分類]
    D --> E{グループタイプ判定}
    E -->|GLOBAL| F[グローバルカバレッジ集計]
    E -->|PATH| G[パス別カバレッジ集計]
    E -->|GLOB| H[ファイル別カバレッジチェック]
    E -->|その他| I[エラー: データ未発見]
    F --> J[check関数実行]
    G --> J
    H --> J
    I --> K[エラーメッセージ追加]
    J --> L{閾値違反?}
    L -->|Yes| K
    L -->|No| M[次のグループ]
    K --> M
    M --> N{全グループ処理完了?}
    N -->|No| E
    N -->|Yes| O{errors.length > 0?}
    O -->|No| Z
    O -->|Yes| P[FAIL_COLOR出力]
    P --> Q[_setError]
    Q --> Z
```

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

### 参照テーブル一覧

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

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

該当なし（メモリ内のカバレッジマップを参照）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| カバレッジ閾値違反 | 実際のカバレッジが閾値を下回る | エラーメッセージを出力し、_setErrorでエラーをセット |
| カバレッジデータ未発見 | 指定されたパスのカバレッジデータが存在しない | エラーメッセージを追加 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし

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

- 出力されるメッセージにはファイルパスが含まれる場合がある
- カバレッジ閾値はプロジェクト設定ファイルで管理されるべき

## 備考

- 閾値の正負で動作が異なる
  - 正の値: パーセンテージ閾値（例: 80 = 80%以上必要）
  - 負の値: 未カバー数閾値（例: -10 = 未カバーが10以下であること）
- 閾値グループは3種類: global、パス、glob
- glob.syncを使用してファイルマッチングを行う（結果はメモ化される）

---

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

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

### 推奨読解順序

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

閾値チェックで扱うデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | L260-264: THRESHOLD_GROUP_TYPES定数 |
| 1-2 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | L228-258: check関数の内部構造 |

**読解のコツ**: check関数はクロージャとして定義されており、name、thresholds、actualsを受け取ってエラー配列を返す。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | L224-435: _checkThresholdメソッド全体 |

**主要処理フロー**:
1. **L225**: coverageThreshold設定の取得
2. **L227**: 設定がなければ早期リターン
3. **L228-258**: check関数の定義
4. **L260-264**: THRESHOLD_GROUP_TYPES定数
5. **L265-334**: ファイルの閾値グループ分類
6. **L363-424**: グループタイプ別のチェック処理
7. **L426-433**: エラー出力と_setError呼び出し

#### Step 3: check関数の詳細

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | L228-258: check関数 |

**主要処理フロー**:
- **L234-237**: 4つの指標（statements, branches, lines, functions）をループ
- **L238-239**: 実際のカバレッジ率と未カバー数を取得
- **L240**: 閾値を取得
- **L243-249**: 負の閾値の場合（未カバー数チェック）
- **L250-253**: 正の閾値の場合（パーセンテージチェック）

#### Step 4: 閾値グループ分類処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | L270-334: coveredFilesSortedIntoThresholdGroup |

**主要処理フロー**:
- **L289-294**: パスマッチング（file.indexOf(absoluteThresholdGroup) === 0）
- **L301-312**: globマッチング（glob.sync使用、メモ化あり）
- **L323-327**: どちらにも該当しない場合はglobalグループに分類

#### Step 5: グループタイプ別チェック処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | L363-424: switch文 |

**主要処理フロー**:
- **L365-379**: GLOBAL: 全ファイルのカバレッジを統合してチェック
- **L381-396**: PATH: パス配下のファイルのカバレッジを統合してチェック
- **L397-411**: GLOB: 各ファイル個別にチェック
- **L412-420**: default: カバレッジデータが見つからないエラー

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

```
CoverageReporter._checkThreshold (L224)
    │
    ├─ check関数定義 (L228-258)
    │      │
    │      └─ statements/branches/lines/functions判定
    │
    ├─ coveredFilesSortedIntoThresholdGroup (L270-334)
    │      │
    │      ├─ path.resolve (L278)
    │      │
    │      └─ glob.sync (L302-304) [メモ化]
    │
    ├─ getFilesInThresholdGroup (L336-339)
    │
    ├─ combineCoverage (L341-359)
    │      │
    │      └─ map.fileCoverageFor().toSummary()
    │
    ├─ check呼び出し (L372, L387, L401-406)
    │
    ├─ this.log (FAIL_COLOR) (L431)
    │
    └─ this._setError (L432)
```

### データフロー図

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

coverageThreshold ─────────▶ グループタイプ分類
                                   │
map (CoverageMap) ────────────────┤
                                   │
                                   ▼
                          ファイル分類
                                   │
                    ┌──────────────┼──────────────┐
                    ▼              ▼              ▼
               GLOBAL          PATH           GLOB
                    │              │              │
                    └──────────────┼──────────────┘
                                   │
                                   ▼
                          combineCoverage
                                   │
                                   ▼
                             check関数
                                   │
                    ┌──────────────┼──────────────┐
                    ▼              ▼              ▼
              statements      branches       lines
                    │              │              │
                    └──────────────┼──────────────┘
                                   │
                                   ▼
                             errors配列
                                   │
                                   ▼
                    FAIL_COLOR(errors.join)
                                   │
                                   ▼
                              stdout
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | ソース | メイン実装ファイル |
| BaseReporter.ts | `packages/jest-reporters/src/BaseReporter.ts` | ソース | _setErrorメソッドを提供 |
| istanbul-lib-coverage | (外部) | ライブラリ | CoverageSummary、CoverageSummaryDataの型 |
| glob | (外部) | ライブラリ | globパターンマッチング |
| @jest/types | `packages/jest-types/` | 型定義 | Config.CoverageThresholdValue型 |
