# 機能設計書 41-テスト

## 概要

本ドキュメントは、VS Codeの統合テスト機能に関する機能設計書である。テストの実行、結果管理、UI表示を包括的に定義する。

### 本機能の処理概要

VS Codeのテスト機能は、拡張機能から提供されるテストフレームワーク（Jest、Mocha、pytest等）と連携し、テストの探索・実行・結果表示を統合的に行うワークベンチ機能である。

**業務上の目的・背景**：ソフトウェア開発においてテスト駆動開発（TDD）や継続的インテグレーション（CI）が重要となる中、開発者がエディタを離れることなくテストを実行・確認できる環境を提供する。これにより開発効率の向上とコード品質の維持を実現する。

**機能の利用シーン**：
- コード変更後のユニットテスト実行
- 特定のテストケースのデバッグ実行
- テスト結果の確認とエラー箇所への遷移
- テストカバレッジの確認
- 継続的なテスト実行（ウォッチモード）

**主要な処理内容**：
1. テストコントローラーの登録と管理（拡張機能からのテストプロバイダー登録）
2. テストアイテムの階層的な収集と差分管理
3. テストプロファイルに基づく実行制御（Run/Debug/Coverage）
4. テスト実行結果の状態管理と永続化
5. テスト結果のUIへの反映（エクスプローラー、デコレーション、出力）
6. テストカバレッジの収集と表示

**関連システム・外部連携**：
- 拡張機能ホスト（Extension Host）経由で各テストフレームワークと連携
- デバッグアダプターとの連携によるデバッグ実行
- ファイルシステムサービスとの連携（テストファイルの監視）
- ストレージサービスとの連携（テスト結果の永続化）

**権限による制御**：ワークスペース信頼機能との連携があり、信頼されていないワークスペースではテスト実行前に確認ダイアログが表示される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | テストビュー | 主画面 | テストエクスプローラー、テストの実行と結果表示 |
| 33 | テスト結果ビュー | 結果表示画面 | テスト実行結果の詳細表示 |

## 機能種別

イベント駆動処理 / データ管理 / UI連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| testIds | string[] | Yes | 実行対象のテストID配列 | TestId形式のバリデーション |
| group | TestRunProfileBitset | Yes | 実行種別（Run/Debug/Coverage） | 定義済みビットセット値 |
| exclude | string[] | No | 除外するテストID配列 | - |
| continuous | boolean | No | 継続実行モードフラグ | - |
| preserveFocus | boolean | No | フォーカス維持フラグ | デフォルトtrue |

### 入力データソース

- 拡張機能からのテストアイテム登録（TestsDiff形式）
- ユーザーのテスト選択操作（UI操作）
- テストプロファイル設定（ユーザー設定/ワークスペース設定）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ITestResult | interface | テスト実行結果 |
| counts | TestStateCount | 状態別テスト数 |
| completedAt | number | 完了時刻（Unix ms） |
| tasks | ITestRunTaskResults[] | タスク別結果 |

### 出力先

- テストビュー（UI表示）
- 問題パネル（エラー情報）
- ストレージ（結果の永続化）
- テレメトリサービス（使用統計）

## 処理フロー

### 処理シーケンス

```
1. テストコントローラー登録
   └─ 拡張機能がIMainThreadTestControllerを実装しregisterTestController()で登録

2. テストアイテム収集
   └─ コントローラーがsyncTests()/refreshTests()でテストを探索
   └─ TestsDiff形式で差分をpublishDiff()経由で通知

3. テスト実行リクエスト
   └─ runTests()でAmbiguousRunTestsRequestを受信
   └─ プロファイル選択とResolvedTestRunRequestへの解決

4. テスト実行
   └─ workspaceTrustRequestServiceで信頼確認
   └─ testResults.createLiveResult()で結果オブジェクト作成
   └─ コントローラー別にrunTests()を並列実行

5. 結果収集
   └─ LiveTestResultに状態更新を蓄積
   └─ updateState()で各テストの状態を更新
   └─ appendMessage()でテストメッセージを追加

6. 完了処理
   └─ markComplete()で実行完了をマーク
   └─ テレメトリ送信
   └─ 結果の永続化（persist=trueの場合）
```

### フローチャート

```mermaid
flowchart TD
    A[テスト実行リクエスト] --> B{ワークスペース信頼?}
    B -->|No| C[確認ダイアログ]
    C -->|拒否| D[実行中止]
    B -->|Yes| E[LiveTestResult作成]
    C -->|許可| E
    E --> F[コントローラー別に分割]
    F --> G[並列実行開始]
    G --> H[状態更新受信]
    H --> I{全タスク完了?}
    I -->|No| H
    I -->|Yes| J[markComplete]
    J --> K[結果永続化]
    K --> L[テレメトリ送信]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-41-01 | 状態遷移制御 | 終端状態（Passed/Failed/Errored/Skipped）から低優先度の状態への遷移は無視される | テスト状態更新時 |
| BR-41-02 | 信頼確認 | テスト実行前にワークスペース信頼の確認が必要 | 全テスト実行時 |
| BR-41-03 | 自動保存 | テスト実行前に開いているファイルを自動保存（設定による） | preserveFocusがfalseの場合 |
| BR-41-04 | 除外テスト | UIで除外設定されたテストは自動的にexcludeリストに追加 | テスト実行時 |

### 計算ロジック

**テスト状態の優先度計算**：
```typescript
// testingStates.ts より
const statesInOrder = [
  TestResultState.Errored,
  TestResultState.Failed,
  TestResultState.Running,
  TestResultState.Queued,
  TestResultState.Passed,
  TestResultState.Skipped,
  TestResultState.Unset,
];
```

複数タスクがある場合、各テストの`ownComputedState`は全タスクの状態の最大優先度となる。

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| テスト結果保存 | IStorageService | INSERT | 実行結果のJSON永続化 |
| インライン出力設定 | IStorageService | UPDATE | showInlineOutput設定 |
| 除外テスト設定 | IStorageService | UPDATE | 除外テストIDリスト |

### テーブル別操作詳細

#### StorageService（ワークスペーススコープ）

| 操作 | 項目（キー） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | inlineTestOutputVisible | boolean | UI設定 |
| INSERT/UPDATE | testing.excludedTests | string[] | 除外テストID |
| SELECT/INSERT | testing.results | ISerializedTestResults[] | 結果履歴 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TEST_TRUST_DENIED | 業務エラー | ワークスペース信頼が拒否された | 結果をmarkComplete()して空の結果を返す |
| CONTROLLER_NOT_FOUND | システムエラー | 指定されたコントローラーIDが存在しない | 該当テストをスキップ |
| PROFILE_NOT_FOUND | 業務エラー | 適切なプロファイルが見つからない | フォールバックプロファイルを使用 |

### リトライ仕様

テスト実行自体のリトライ機能は提供されない。失敗したテストは結果に記録され、ユーザーが手動で再実行する。

## トランザクション仕様

テスト実行はトランザクション制御を行わない。各状態更新は即座にUIに反映され、結果の永続化は実行完了時に一括で行われる。

## パフォーマンス要件

- テストアイテムの差分適用は非同期で処理
- 大量のテストアイテム（数千件）でもUIの応答性を維持
- テスト結果の永続化はLazy評価でシリアライズ

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

- テスト実行はワークスペース信頼機能と連携
- テストコードはワークスペース内で実行されるため、任意のコード実行が可能
- テレメトリには機密情報（テスト名等）は含めない

## 備考

- テスト機能は拡張機能API（vscode.tests）を通じて拡張機能から利用される
- 組み込みのテストフレームワークは提供されず、すべて拡張機能経由

---

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

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

### 推奨読解順序

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

テスト機能で使用される主要なデータ型を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | testTypes.ts | `src/vs/workbench/contrib/testing/common/testTypes.ts` | TestResultState列挙型（14-22行目）、ITestRunProfile（77-86行目）、ResolvedTestRunRequest（98-110行目）を確認 |
| 1-2 | testId.ts | `src/vs/workbench/contrib/testing/common/testId.ts` | TestId クラスによるテストの階層的ID管理 |
| 1-3 | testResult.ts | `src/vs/workbench/contrib/testing/common/testResult.ts` | ITestResult インターフェース（40-92行目）、LiveTestResult クラス |

**読解のコツ**: VS Codeでは`createDecorator`パターンでサービスインターフェースを定義し、依存性注入で実装を解決する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | testService.ts | `src/vs/workbench/contrib/testing/common/testService.ts` | ITestService インターフェース（377-480行目）が機能のコアAPI定義 |

**主要処理フロー**:
1. **27行目**: `ITestService = createDecorator<ITestService>('testService')` でサービスID定義
2. **377-480行目**: ITestServiceインターフェースの全メソッド定義
3. **443行目**: `runTests()` がテスト実行のエントリーポイント

#### Step 3: サービス実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | testServiceImpl.ts | `src/vs/workbench/contrib/testing/common/testServiceImpl.ts` | TestService クラスの実装（39-449行目） |

**主要処理フロー**:
- **87-127行目**: コンストラクタでの初期化、依存サービスの注入
- **154-211行目**: `runTests()` でプロファイル解決とテスト実行
- **251-295行目**: `runResolvedTests()` で実際のテスト実行処理
- **326-331行目**: `publishDiff()` でテスト差分の適用

#### Step 4: テスト結果管理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | testResult.ts | `src/vs/workbench/contrib/testing/common/testResult.ts` | LiveTestResult クラス（279-625行目） |
| 4-2 | testResultService.ts | `src/vs/workbench/contrib/testing/common/testResultService.ts` | ITestResultService インターフェースと結果管理 |

**主要処理フロー**:
- **279行目**: LiveTestResult クラス定義開始
- **424-443行目**: `updateState()` でテスト状態更新
- **479-507行目**: `markComplete()` で実行完了処理とテレメトリ送信

#### Step 5: UI層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | testingExplorerView.ts | `src/vs/workbench/contrib/testing/browser/testingExplorerView.ts` | TestingExplorerView クラスでテストツリーUI |
| 5-2 | testExplorerActions.ts | `src/vs/workbench/contrib/testing/browser/testExplorerActions.ts` | テスト実行アクションの定義 |

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

```
TestService (testServiceImpl.ts)
    │
    ├─ MainThreadTestCollection (mainThreadTestCollection.ts)
    │      └─ テストアイテムの階層管理
    │
    ├─ ITestProfileService (testProfileService.ts)
    │      └─ 実行プロファイルの管理
    │
    ├─ ITestResultService (testResultService.ts)
    │      ├─ LiveTestResult (testResult.ts)
    │      │      └─ 実行中のテスト結果管理
    │      └─ HydratedTestResult (testResult.ts)
    │             └─ 永続化された結果の復元
    │
    └─ IMainThreadTestController (testService.ts)
           └─ 拡張機能ホストへのテスト実行委譲
```

### データフロー図

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

テスト選択         ───▶ TestService.runTests()      ───▶ ITestResult
(UI操作)                      │
                              ▼
                    プロファイル解決
                              │
                              ▼
                    runResolvedTests()
                              │
                              ▼
                    LiveTestResult作成    ───────────▶ UI更新
                              │                        (TestingExplorerView)
                              ▼
                    コントローラー実行     ◀─────────── 状態更新
                              │
                              ▼
                    markComplete()        ───────────▶ 結果永続化
                              │                        (StorageService)
                              ▼
                    テレメトリ送信        ───────────▶ テレメトリ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| testService.ts | `src/vs/workbench/contrib/testing/common/testService.ts` | ソース | サービスインターフェース定義 |
| testServiceImpl.ts | `src/vs/workbench/contrib/testing/common/testServiceImpl.ts` | ソース | サービス実装 |
| testTypes.ts | `src/vs/workbench/contrib/testing/common/testTypes.ts` | ソース | 型定義 |
| testResult.ts | `src/vs/workbench/contrib/testing/common/testResult.ts` | ソース | テスト結果管理 |
| testResultService.ts | `src/vs/workbench/contrib/testing/common/testResultService.ts` | ソース | 結果サービス |
| testProfileService.ts | `src/vs/workbench/contrib/testing/common/testProfileService.ts` | ソース | プロファイル管理 |
| mainThreadTestCollection.ts | `src/vs/workbench/contrib/testing/common/mainThreadTestCollection.ts` | ソース | テストコレクション |
| testingExplorerView.ts | `src/vs/workbench/contrib/testing/browser/testingExplorerView.ts` | ソース | UI（テストビュー） |
| testExplorerActions.ts | `src/vs/workbench/contrib/testing/browser/testExplorerActions.ts` | ソース | アクション定義 |
| testingContextKeys.ts | `src/vs/workbench/contrib/testing/common/testingContextKeys.ts` | ソース | コンテキストキー |
| testing.contribution.ts | `src/vs/workbench/contrib/testing/browser/testing.contribution.ts` | ソース | 機能登録 |
| configuration.ts | `src/vs/workbench/contrib/testing/common/configuration.ts` | 設定 | 設定項目定義 |
