# バッチ設計書 25-doctest

## 概要

本ドキュメントは、Juliaドキュメント内のコード例（doctest）を検証するMakefileターゲット `make -C doc doctest=true` のバッチ設計書である。

### 本バッチの処理概要

本バッチは、Juliaのドキュメントソースおよびdocstring内に記載されたコード例（jldoctestブロック）を実際に実行し、期待される出力と一致するかを自動的に検証する。ドキュメントの品質保証において、コード例が最新のJulia動作と整合していることを保証するために使用される。

**業務上の目的・背景**：Juliaのドキュメントには多数のコード例（doctest）が含まれており、Juliaのバージョンアップや機能変更に伴い、これらのコード例が実際の動作と乖離するリスクがある。本バッチはdoctestを自動実行することで、ドキュメント内のコード例の正確性を継続的に保証する。

**バッチの実行タイミング**：ドキュメントやdocstring内のjldoctestブロックを変更した際に実行する。CIパイプラインでも実行される。AGENTS.mdによると、doctestの変更後は必ず実行することが求められている。

**主要な処理内容**：
1. UnicodeDataファイルの準備（depsターゲット）
2. Documenter.jlの依存関係インストール
3. 各モジュール（Base, Core, 標準ライブラリ）のDocTestSetupの設定
4. Documenter.makedocsのdoctest=trueモードでの実行
5. 各jldoctestブロックの実行と期待出力との比較
6. doctest=fixモードでの自動修正（オプション）

**前後の処理との関連**：HTML生成（No.23）やPDF生成（No.24）と同じmake.jlスクリプトを使用する。ドキュメント変更後、HTML/PDF生成前にdoctestを実行して品質を確認することが推奨される。Reviseモードを使用すると、ソースコード変更を反映した上でdoctestを実行可能。

**影響範囲**：doctest=fixモードの場合、ドキュメントソースファイルが直接修正される。doctest=trueモードの場合は読み取り専用であり、検証結果のみを報告する。

## バッチ種別

品質検証 / テスト実行

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（doctest変更時、CI実行時） |
| 実行時刻 | 任意 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 手動実行（make -C doc doctest=true）またはCI自動実行 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Julia実行バイナリ | ビルド済みのJulia実行ファイルが利用可能であること |
| Documenter.jl | 依存関係として自動インストール |
| Revise.jl（任意） | revise=trueオプション使用時に必要 |

### 実行可否判定

Julia実行バイナリが存在し、ドキュメントソースが正常に読み込める場合に実行可能。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| doctest | 文字列 | Yes | なし | "true"で検証実行、"fix"で自動修正、"only"で検証のみ |
| revise | 文字列 | No | 未設定 | "true"を指定するとRevise.jlを使用してソース変更を反映 |
| buildroot | パス | No | ソースツリー | ビルドルートディレクトリ |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| doc/src/*.md | Markdown | ドキュメントソースファイル群（jldoctestブロックを含む） |
| base/*.jl | Julia | Base関数のdocstring内のjldoctestブロック |
| stdlib/*/src/*.jl | Julia | 標準ライブラリのdocstring内のjldoctestブロック |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| 標準出力/エラー出力 | テキスト | doctest検証結果（成功/失敗の報告） |
| ソースファイル（fix時） | Markdown/Julia | doctest=fixの場合、期待出力を更新 |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | doctest=fix時はソースファイルが直接修正される |
| 出力先 | doc/src/ および ソースファイル |
| 文字コード | UTF-8 |
| 区切り文字 | 該当なし |

## 処理フロー

### 処理シーケンス

```
1. 依存関係の準備
   ├─ UnicodeDataファイルの取得
   └─ Documenter.jlプロジェクトのinstantiate
2. Reviseの設定（revise=true時）
   ├─ Revise.jlのactivate/instantiate
   ├─ Base, Core.Compiler, 標準ライブラリのRevise.track
   └─ Revise.revise()で最新変更を反映
3. DocTestSetupの設定
   ├─ 各stdlibに using $STDLIB をsetup
   ├─ SparseArrays: using SparseArrays, LinearAlgebra
   ├─ UUIDs: using UUIDs, Random
   ├─ Pkg: using Pkg, Pkg.Artifacts
   └─ Base: 空のsetup
4. Documenter.makedocs実行（doctest=trueモード）
   ├─ 全ドキュメントソース内のjldoctestブロックを検出
   ├─ 各doctestを実行し、出力を期待値と比較
   └─ 不一致があれば失敗報告（fix時は自動修正）
5. 結果報告
```

### フローチャート

```mermaid
flowchart TD
    A[make doctest=true 実行] --> B[依存関係準備]
    B --> C{revise=true?}
    C -->|Yes| D[Revise.jlロード・track]
    C -->|No| E[DocTestSetup設定]
    D --> E
    E --> F[makedocs doctest=trueモード]
    F --> G[jldoctestブロック検出]
    G --> H[各doctestを実行]
    H --> I{出力一致?}
    I -->|Yes| J[成功]
    I -->|No| K{doctest=fix?}
    K -->|Yes| L[ソースファイル自動修正]
    K -->|No| M[失敗報告]
    L --> N[結果出力]
    J --> N
    M --> N
    N --> O[バッチ終了]
```

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

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

本バッチはデータベースを使用しない。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 該当なし | 該当なし | 該当なし | 該当なし |

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 該当なし | doctest失敗 | コード例の出力が期待値と不一致 | doctest=fixで自動修正、または手動で修正 |
| 該当なし | 実行エラー | jldoctest内のコードが例外を発生 | コード例の修正が必要 |
| 該当なし | setup失敗 | DocTestSetupのコードが失敗 | setup用のusingステートメントを確認 |

### リトライ仕様

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

### 障害時対応

doctest失敗時は `doctest=fix` オプションで自動修正を試みることができる。それでも解決しない場合はドキュメントソースまたはdocstringを手動で修正する。フィルタやラベル、セットアップコードの追加が必要な場合がある（doc/src/devdocs/contributing/jldoctests.md参照）。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 該当なし |
| コミットタイミング | 該当なし |
| ロールバック条件 | doctest=fix時はgitで変更を元に戻すことが可能 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 数百件のdoctestブロック |
| 目標処理時間 | 最大15分（AGENTS.mdの記載に基づく） |
| メモリ使用量上限 | 数GB（全モジュールのロードが必要） |

## 排他制御

同じビルドディレクトリに対する同時実行は想定されていない。doctest=fixモードではソースファイルを変更するため、並行実行でファイル競合が発生する可能性がある。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | バッチ開始時 | Documenterの起動メッセージ |
| 進捗ログ | 処理中 | 各doctestの実行結果（成功/失敗） |
| 終了ログ | バッチ終了時 | 全体の成功/失敗サマリー |
| エラーログ | エラー発生時 | 失敗したdoctestの詳細（期待出力vs実際出力） |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| CI実行結果 | doctest失敗 | GitHub Actions / BuildKite |

## 備考

- AGENTS.mdによると、doctestは最大15分かかる可能性があり、タイムアウト前に強制終了してはならない
- Reviseモードを使用すると、システムイメージの再ビルドなしにBase/stdlibの変更を反映してdoctestを実行可能
- 実行コマンド例: `make -C doc doctest=true revise=true`
- juliaupのバイナリを使用する場合: `make -C doc doctest=true revise=true JULIA_EXECUTABLE=$HOME/.juliaup/bin/julia`
- doctestの書き方やフィルタ、ラベル、セットアップコードの詳細は `doc/src/devdocs/contributing/jldoctests.md` を参照
- ファイルパス: `doc/Makefile`（htmlターゲット経由）、`doc/make.jl`（メインスクリプト）
