# 帳票設計書 4-CoverageReporter

## 概要

本ドキュメントは、Jestテストフレームワークにおけるコードカバレッジレポーター「CoverageReporter」の設計仕様を定義する。CoverageReporterは、テスト実行時のコードカバレッジ情報を収集・集約し、istanbul-reportsを使用して複数形式（json、text、lcov、clover等）でカバレッジレポートを生成するレポーターである。

### 本帳票の処理概要

CoverageReporterは、各テスト実行時に収集されたカバレッジ情報を集約し、テスト完了後にカバレッジレポートを生成する。V8カバレッジとBabelカバレッジの両方に対応し、未テストファイルのカバレッジ情報も収集できる。生成されたカバレッジレポートは、coverageDirectoryで指定されたディレクトリに出力され、coverageThresholdで設定された閾値チェックも行う。

**業務上の目的・背景**：コードカバレッジはソフトウェア品質の重要な指標であり、テストがコードのどの部分をカバーしているかを可視化する。CoverageReporterは、Statements、Branches、Functions、Linesの各カバレッジ率を計算し、閾値を下回った場合にエラーを報告することで、品質基準の維持を支援する。CI/CDパイプラインでのカバレッジゲート、SonarQubeなどの品質管理ツールとの連携にも使用される。

**帳票の利用シーン**：`jest --coverage`コマンドで実行した場合、または`collectCoverage: true`設定時に使用される。CI/CDでのカバレッジレポート生成、品質ダッシュボードへのデータ連携、開発者によるカバレッジ確認などに利用される。

**主要な出力内容**：
1. JSON形式のカバレッジデータ（coverage-final.json）
2. テキスト形式のカバレッジサマリー（コンソール出力）
3. LCOV形式のカバレッジレポート（lcov.info）
4. HTML形式のインタラクティブレポート（lcov-report/）
5. Clover/Cobertura XML形式のレポート
6. カバレッジ閾値違反のエラーメッセージ

**帳票の出力タイミング**：onRunCompleteイベント時、すべてのテスト実行が完了した後にカバレッジレポートが生成される。

**帳票の利用者**：ソフトウェア開発者、QAエンジニア、DevOpsエンジニア、プロジェクトマネージャー、品質管理チーム

## 帳票種別

カバレッジレポート / 品質指標レポート

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| CLI-01 | コマンドライン | N/A | `jest --coverage`コマンド実行 |
| CI-01 | CI/CDパイプライン | N/A | 設定によるカバレッジ収集 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | JSON / テキスト / LCOV / HTML / XML |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | coverage-final.json, lcov.info, clover.xml 等 |
| 出力方法 | ファイル出力 / コンソール出力 |
| 文字コード | UTF-8 |

### 出力ディレクトリ

| 項目 | 内容 |
|-----|------|
| デフォルトパス | `<rootDir>/coverage/` |
| 設定オプション | `coverageDirectory` |
| HTML出力パス | `<coverageDirectory>/lcov-report/` |

## 帳票レイアウト

### レイアウト概要

CoverageReporterは複数の出力形式をサポートし、それぞれ異なるレイアウトを持つ。

```
coverage/
├── coverage-final.json     # JSON形式の詳細データ
├── lcov.info               # LCOV形式
├── clover.xml              # Clover XML形式
├── cobertura-coverage.xml  # Cobertura XML形式
└── lcov-report/            # HTML形式
    ├── index.html
    ├── base.css
    └── <各ファイルのカバレッジ詳細>
```

### テキスト形式（コンソール出力）

```
----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
----------|---------|----------|---------|---------|-------------------
All files |   80.00 |    75.00 |   90.00 |   85.00 |
 src/     |   80.00 |    75.00 |   90.00 |   85.00 |
  file.ts |   80.00 |    75.00 |   90.00 |   85.00 | 10-15,20
----------|---------|----------|---------|---------|-------------------
```

### カバレッジサマリー項目

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | File | ファイル名/ディレクトリ名 | CoverageMap | パス表示 |
| 2 | % Stmts | Statement カバレッジ率 | CoverageSummary.statements | パーセント |
| 3 | % Branch | Branch カバレッジ率 | CoverageSummary.branches | パーセント |
| 4 | % Funcs | Function カバレッジ率 | CoverageSummary.functions | パーセント |
| 5 | % Lines | Line カバレッジ率 | CoverageSummary.lines | パーセント |
| 6 | Uncovered Line #s | 未カバー行番号 | CoverageSummary | 行番号リスト |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| カバレッジ収集 | `--coverage`オプションまたは`collectCoverage: true` | Yes |
| ファイル収集パターン | `collectCoverageFrom`で指定されたパターン | No |

### カバレッジ閾値チェック

| 閾値タイプ | 説明 | 設定例 |
|-----------|------|--------|
| global | 全体のカバレッジ閾値 | `{ statements: 80, branches: 70 }` |
| パス指定 | 特定パスのカバレッジ閾値 | `{ "./src/": { lines: 90 } }` |
| glob指定 | globパターンでのカバレッジ閾値 | `{ "**/*.ts": { functions: 80 } }` |

### 改ページ条件

N/A（ファイル出力/コンソール出力）

## データベース参照仕様

### 参照テーブル一覧

N/A（実行時に収集されたカバレッジデータを使用）

### データ構造参照

#### V8CoverageResult

| 参照項目 | 帳票項目との対応 | 用途 |
|---------|----------------|------|
| result | カバレッジデータ | V8形式のカバレッジ情報 |
| codeTransformResult | ソースマップ | トランスパイル後のマッピング |

#### istanbulCoverage.CoverageMap

| 参照項目 | 帳票項目との対応 | 用途 |
|---------|----------------|------|
| files() | ファイル一覧 | カバー対象ファイル |
| fileCoverageFor() | ファイル別カバレッジ | 詳細データ取得 |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| カバレッジ率 | (covered / total) * 100 | 小数点2桁 | istanbul-lib-coverageで計算 |
| 未カバー数 | total - covered | なし | 閾値チェックで使用 |

### 閾値チェックロジック

| 条件 | 判定 | 結果 |
|------|------|------|
| threshold >= 0 かつ actual < threshold | 閾値未達 | エラー |
| threshold < 0 かつ uncovered > -threshold | 未カバー数超過 | エラー |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[onTestResult] --> B{V8 Coverage?}
    B -->|Yes| C[V8結果を_v8CoverageResultsに追加]
    B -->|No| D[Babel結果を_coverageMapにマージ]
    C --> E[onRunComplete]
    D --> E
    E --> F[_addUntestedFiles]
    F --> G[未テストファイルのカバレッジ収集]
    G --> H[_getCoverageResult]
    H --> I{V8 Provider?}
    I -->|Yes| J[V8カバレッジをIstanbul形式に変換]
    I -->|No| K[ソースマップ変換]
    J --> L[レポーター実行]
    K --> L
    L --> M[各形式でレポート出力]
    M --> N[_checkThreshold]
    N --> O{閾値違反?}
    O -->|Yes| P[エラー設定]
    O -->|No| Q[完了]
    P --> Q
```

### 未テストファイル収集フロー

```mermaid
flowchart TD
    A[_addUntestedFiles] --> B[collectCoverageFromパターンでファイル抽出]
    B --> C{ファイルあり?}
    C -->|No| D[スキップ]
    C -->|Yes| E[Worker起動]
    E --> F[各ファイルのカバレッジ収集]
    F --> G[結果をマージ]
    G --> H[Worker終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| カバレッジ閾値未達 | actual < threshold | "Jest: "{name}" coverage threshold for {key} ({threshold}%) not met: {actual}%" | 赤色で表示、エラー設定 |
| 未カバー数超過 | threshold < 0 かつ uncovered > -threshold | "Jest: Uncovered count for {key} ({uncovered}) exceeds {name} threshold ({-threshold})" | 赤色で表示 |
| カバレッジデータなし | 指定パスにデータがない | "Jest: Coverage data for {path} was not found." | 赤色で表示 |
| レポート出力失敗 | 出力時のエラー | "Failed to write coverage reports: ERROR: {message}" | 赤色で表示 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | 数千ファイルまで対応 |
| 目標出力時間 | ファイル数に依存（ワーカーによる並列処理） |
| 同時処理数 | globalConfig.maxWorkers に依存 |

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

- カバレッジレポートにはソースコードの構造が含まれるため、公開範囲に注意
- HTMLレポートはファイルパスと行番号を含むため、機密コードの露出に注意
- CI/CDでのレポート保存先のアクセス制御を適切に設定すること

## 備考

- V8カバレッジプロバイダーはBabelトランスパイルなしで高速なカバレッジ収集が可能
- coverageReportersオプションで出力形式を指定可能（デフォルト: ["json", "text", "lcov", "clover"]）
- useStderrかつcoverageReportersが空の場合、"text-summary"がデフォルトで追加される
- coverageThresholdで負の値を指定すると、未カバー数の上限チェックとなる

---

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

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

### 推奨読解順序

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

まず、カバレッジ関連のデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | クラスのプロパティ定義（42-46行目）を確認 |
| 1-2 | @jest/test-result | `node_modules/@jest/test-result` | V8CoverageResult型を確認 |
| 1-3 | istanbul-lib-coverage | `node_modules/istanbul-lib-coverage` | CoverageMap, CoverageSummary型を確認 |

**読解のコツ**: V8カバレッジとBabelカバレッジの2つのカバレッジプロバイダーがあることを意識して読む。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | コンストラクタ（50-57行目） |

**主要処理フロー**:
1. **50-57行目**: コンストラクタ - context、coverageMap、sourceMapStore、v8CoverageResultsの初期化
2. **53行目**: `istanbulCoverage.createCoverageMap({})` - 空のカバレッジマップ作成

#### Step 3: テスト結果からのカバレッジ収集を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | onTestResult（59-68行目） |

**主要処理フロー**:
- **59-68行目**: `onTestResult` - V8カバレッジまたはBabelカバレッジを収集
- **60-63行目**: V8カバレッジの場合、_v8CoverageResultsに追加
- **65-67行目**: Babelカバレッジの場合、_coverageMapにマージ

#### Step 4: レポート生成処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | onRunComplete（70-107行目） |

**主要処理フロー**:
- **70-107行目**: `onRunComplete` - メインのレポート生成処理
- **74行目**: `_addUntestedFiles` - 未テストファイルのカバレッジ収集
- **75行目**: `_getCoverageResult` - カバレッジ結果の取得
- **78-81行目**: coverageReportersが空の場合、"text-summary"を追加
- **83-94行目**: 各レポーターでレポート生成
- **106行目**: `_checkThreshold` - 閾値チェック

#### Step 5: 未テストファイル収集を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | _addUntestedFiles（109-222行目） |

**主要処理フロー**:
- **109-222行目**: `_addUntestedFiles` - 未テストファイルのカバレッジ収集
- **116-129行目**: collectCoverageFromパターンでファイルを抽出
- **145-155行目**: ワーカーの起動（maxWorkers > 1の場合は並列実行）
- **157-207行目**: 各ファイルのカバレッジを収集
- **219-221行目**: ワーカーの終了

#### Step 6: V8カバレッジの変換処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | _getCoverageResult（437-516行目） |

**主要処理フロー**:
- **441-504行目**: V8カバレッジプロバイダーの場合の処理
- **442-444行目**: `mergeProcessCovs` - 複数プロセスのカバレッジをマージ
- **455-492行目**: V8カバレッジをIstanbul形式に変換（v8toIstanbul使用）
- **507-515行目**: Babelカバレッジの場合、ソースマップ変換

#### Step 7: 閾値チェック処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 7-1 | CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | _checkThreshold（224-435行目） |

**主要処理フロー**:
- **228-258行目**: `check`関数 - 閾値チェックの実装
- **260-264行目**: THRESHOLD_GROUP_TYPES - グループタイプの定義
- **270-334行目**: ファイルを閾値グループに分類
- **363-434行目**: 各グループタイプごとの閾値チェック

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

```
CoverageReporter
    │
    ├─ BaseReporter (継承)
    │
    ├─ onTestResult
    │      ├─ _v8CoverageResults.push (V8の場合)
    │      └─ _coverageMap.merge (Babelの場合)
    │
    ├─ onRunComplete
    │      │
    │      ├─ _addUntestedFiles
    │      │      ├─ hasteFS.matchFilesWithGlob
    │      │      └─ CoverageWorker.worker
    │      │
    │      ├─ _getCoverageResult
    │      │      ├─ mergeProcessCovs (@bcoe/v8-coverage)
    │      │      ├─ v8toIstanbul
    │      │      └─ sourceMapStore.transformCoverage
    │      │
    │      ├─ istanbulReports.create
    │      │      └─ execute (レポート生成)
    │      │
    │      └─ _checkThreshold
    │             ├─ check (閾値判定)
    │             ├─ combineCoverage
    │             └─ glob.sync (パターンマッチ)
    │
    └─ getWatermarks
```

### データフロー図

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

TestResult.v8Coverage ─────▶ onTestResult
TestResult.coverage           │
       │                      ├─▶ _v8CoverageResults ──────────┐
       │                      └─▶ _coverageMap ─────────────────┤
       │                                                        │
       │                                                        ▼
       │                      onRunComplete ◀──────────────────┘
       │                           │
       │                           ├─▶ _addUntestedFiles
       │                           │         │
       │                           │         └─▶ CoverageWorker
       │                           │
       │                           ├─▶ _getCoverageResult
       │                           │         │
       │                           │         ├─▶ V8 → Istanbul変換
       │                           │         └─▶ ソースマップ変換
       │                           │
       │                           ├─▶ istanbulReports ────────▶ json, text, lcov, html等
       │                           │
       └──────────────────────────▶ _checkThreshold ──────────▶ 閾値エラー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| CoverageReporter.ts | `packages/jest-reporters/src/CoverageReporter.ts` | ソース | カバレッジレポーター実装 |
| CoverageWorker.ts | `packages/jest-reporters/src/CoverageWorker.ts` | ソース | 未テストファイルカバレッジ収集ワーカー |
| getWatermarks.ts | `packages/jest-reporters/src/getWatermarks.ts` | ソース | ウォーターマーク設定取得 |
| BaseReporter.ts | `packages/jest-reporters/src/BaseReporter.ts` | ソース | 基底クラス |
| types.ts | `packages/jest-reporters/src/types.ts` | ソース | 型定義 |
| index.ts | `packages/jest-reporters/src/index.ts` | ソース | エクスポート定義 |
