# 機能設計書 9-@jest/test-sequencer

## 概要

本ドキュメントは、Jestのテスト実行順序決定を担当する「@jest/test-sequencer」の機能設計を記述したものである。

### 本機能の処理概要

@jest/test-sequencerパッケージは、テストファイルの実行順序を決定するためのモジュールである。前回の実行結果（失敗/成功、実行時間）をキャッシュから読み込み、最適なテスト実行順序を計算する。また、シャーディング機能により、テストスイートを複数のマシンに分散実行することも可能である。

**業務上の目的・背景**：大規模なテストスイートでは、テストの実行順序がテスト全体の実行時間と開発者体験に大きな影響を与える。失敗したテストを先に実行することで、開発者は問題を早期に発見でき、長時間かかるテストを先に開始することで、ワーカーのアイドル時間を削減できる。また、CI環境でのシャーディングにより、テスト実行時間を短縮できる。

**機能の利用シーン**：
- テスト実行順序の最適化
- 失敗テストの優先実行
- CI環境でのテストシャーディング（--shard=M/N）
- カスタムシーケンサーの基底クラスとして

**主要な処理内容**：
1. 前回実行結果のキャッシュ読み込み
2. 失敗テストの優先順位付け
3. 実行時間に基づくソート（長いテストを先に）
4. ファイルサイズに基づくソート（キャッシュがない場合）
5. シャーディングによるテスト分割
6. 実行結果のキャッシュ保存

**関連システム・外部連携**：
- jest-haste-map: ファイルサイズ情報の取得
- ファイルシステム: キャッシュの読み書き
- @jest/core: テスト実行のスケジューリング

**権限による制御**：特になし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| N/A | N/A | N/A | 本機能はテスト順序決定であり、画面は存在しない |

## 機能種別

テストスケジューリング / キャッシュ管理 / シャーディング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| tests | Array<Test> | Yes | テストファイルリスト | 空でないこと |
| options | ShardOptions | No | シャーディングオプション | shardIndex/shardCountの整合性 |

### 入力データソース

- TestSchedulerからのテストファイルリスト
- キャッシュファイル（前回実行結果）
- CLIオプション（--shard）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| sortedTests | Array<Test> | ソート済みテストリスト |
| shardedTests | Array<Test> | シャーディング後のテストリスト |

### 出力先

@jest/coreのTestSchedulerへ

## 処理フロー

### 処理シーケンス

```
1. テストリスト受信
   └─ TestSchedulerからテストファイルリストを受信
2. シャーディング（オプション）
   └─ --shard指定時にテストを分割
3. キャッシュ読み込み
   └─ 前回実行結果をキャッシュから読み込み
4. ソート
   └─ 失敗優先→実行時間順にソート
5. 結果返却
   └─ ソート済みリストを返却
```

### フローチャート

```mermaid
flowchart TD
    A[テストリスト受信] --> B{シャーディング?}
    B -->|Yes| C[shard でテスト分割]
    B -->|No| D[キャッシュ読み込み]
    C --> D
    D --> E{キャッシュ存在?}
    E -->|Yes| F[失敗テスト優先]
    E -->|No| G[ファイルサイズでソート]
    F --> H[実行時間でソート]
    H --> I[ソート済みリスト返却]
    G --> I
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 失敗優先 | 前回失敗したテストを先に実行 | キャッシュ存在時 |
| BR-002 | 長時間優先 | 実行時間が長いテストを先に実行 | キャッシュ存在時 |
| BR-003 | サイズ優先 | キャッシュがない場合はファイルサイズで判断 | キャッシュなし時 |
| BR-004 | シャードハッシュ | テストパスのSHA1ハッシュでシャード分配 | shard指定時 |
| BR-005 | シャード分配 | なるべく均等にシャードに分配 | shard指定時 |

### 計算ロジック

シャード位置の計算:
```javascript
const shardRest = suiteLength % shardCount;
const ratio = suiteLength / shardCount;
// 各シャードのサイズを計算（余りは前のシャードに分配）
const shardSize = shardIndex < shardRest ? Math.ceil(ratio) : Math.floor(ratio);
```

ソート優先度:
1. 失敗テスト > 成功テスト
2. 実行時間が長いテスト > 短いテスト
3. ファイルサイズが大きいテスト > 小さいテスト

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

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

データベース操作は本パッケージでは行わないが、ファイルシステムへのキャッシュ読み書きを行う。

| 操作 | 対象 | 操作種別 | 概要 |
|-----|-----|---------|------|
| キャッシュ読込 | perf-cache-{id} | READ | 前回実行結果の読み込み |
| キャッシュ保存 | perf-cache-{id} | WRITE | 実行結果の保存 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| CACHE_READ_ERROR | キャッシュ読み込みエラー | キャッシュファイル破損 | キャッシュを無視して続行 |
| INVALID_SHARD | シャード設定エラー | 不正なシャード指定 | shardIndex/shardCountを確認 |

### リトライ仕様

キャッシュ読み込み/書き込みにリトライはない（エラー時は無視）

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

トランザクション処理は本パッケージには存在しない

## パフォーマンス要件

- ソート処理はO(n log n)
- シャーディング処理はO(n)
- キャッシュ読み込みは初回のみ

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

- キャッシュファイルにはテストパスと実行時間のみを保存
- 機密情報はキャッシュに含まれない

## 備考

- カスタムシーケンサーを作成する場合はTestSequencerを継承
- testSequencer設定でカスタムシーケンサーを指定可能

---

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

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

### 推奨読解順序

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

シーケンサーで使用される型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `packages/jest-test-sequencer/src/index.ts` | Cache、ShardOptions型 |

**読解のコツ**: Cacheは `{ [testPath]: [status, duration] }` の形式でテスト結果を保存。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/jest-test-sequencer/src/index.ts` | TestSequencerクラス |

**主要処理フロー**:
1. **52-65行目**: _getCachePath（キャッシュファイルパス取得）
2. **67-88行目**: _getCache（キャッシュ読み込み）
3. **90-102行目**: _shardPosition（シャード位置計算）
4. **125-159行目**: shard（テストのシャーディング）
5. **175-217行目**: sort（テストのソート）
6. **219-221行目**: allFailedTests（失敗テストのフィルタ）
7. **223-244行目**: cacheResults（結果のキャッシュ保存）

#### Step 3: ソートロジックの詳細を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `packages/jest-test-sequencer/src/index.ts` | sortメソッド |

**主要処理フロー**:
- **175-192行目**: ソートの説明コメント（重要）
- **194-196行目**: ファイルサイズの取得
- **198-200行目**: 実行時間の設定
- **201-216行目**: ソート比較関数

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

```
@jest/test-sequencer/index.ts (TestSequencer)
    │
    ├─ shard (シャーディング)
    │      │
    │      └─ _shardPosition (シャード位置計算)
    │
    ├─ sort (ソート)
    │      │
    │      ├─ _getCache (キャッシュ読み込み)
    │      │      └─ _getCachePath
    │      │
    │      ├─ hasFailed (失敗判定)
    │      │
    │      └─ time (実行時間取得)
    │
    ├─ allFailedTests (失敗テストフィルタ)
    │      └─ hasFailed
    │
    └─ cacheResults (結果キャッシュ)
           └─ _getCache
```

### データフロー図

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

Test[] ──────────────────▶ shard() ────────────────▶ シャーディング済みTest[]
    │                           │
    │                           ▼
    │                    SHA1ハッシュ計算
    │                           │
    │                           ▼
    │                    シャード範囲選択
    │                           │
    ▼                           ▼
キャッシュファイル ─────▶ _getCache() ───────────▶ Cache オブジェクト
    │                           │
    ▼                           ▼
Test[] ──────────────────▶ sort() ─────────────────▶ ソート済みTest[]
    │                           │
    │                           ▼
    │                    失敗優先 → 実行時間順
    │                           │
    ▼                           ▼
AggregatedResult ───────▶ cacheResults() ─────────▶ キャッシュ更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `packages/jest-test-sequencer/src/index.ts` | ソース | TestSequencerクラス |
| package.json | `packages/jest-test-sequencer/package.json` | 設定 | パッケージ定義 |
