# 機能設計書 87-テストフレームワーク

## 概要

本ドキュメントは、mrubyのmruby-test gemが提供するテスト実行フレームワーク（mrbtest）の機能設計を記述する。mruby本体および各gemのテストを統合的に実行するテストランナーとテスト支援機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：mrubyおよびmrbgemsの品質保証のため、統合的なテスト実行環境が必要である。本gemはmrbtestバイナリを生成し、全gemのテストを自動収集・統合・実行する。各gemのテストは独立したmrb_stateで実行され、テスト結果が集約される。

**機能の利用シーン**：mrubyのビルド後のテスト実行（`rake test`）、gem開発時のテスト実行、CI/CD環境での自動テスト、回帰テスト。

**主要な処理内容**：
1. mrbtestバイナリの生成（driver.c）
2. テストアサーション関数の提供（assert.rb → mrbtest_assert_irep）
3. 各gemのテストコード自動収集とコード生成（mrbgem.rake）
4. テスト結果の集約・レポート（ok/ko/kill/warning/skip）
5. vformatテスト支援（mrb_format関数のテスト用ラッパー）
6. パターンマッチによるテスト名フィルタリング

**関連システム・外部連携**：mrubyビルドシステム（Rakefile）、全mrbgems

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLI | 結果表示画面 | mrbtestの標準出力にテスト結果を表示 |

## 機能種別

テスト実行処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -v | フラグ | No | 詳細出力モード | - |

### 入力データソース

各gemのtest/ディレクトリに配置されたテストファイル（.rb, .c）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| テスト結果 | 文字列 | 各テストのpass/fail情報 |
| 終了コード | Integer | EXIT_SUCCESS(全pass) / EXIT_FAILURE(fail有) |

### 出力先

標準出力、プロセス終了コード

## 処理フロー

### 処理シーケンス

```
1. main(argc, argv)
   ├─ print_hint() でバナー出力
   ├─ mrb_open() でインタプリタ生成
   ├─ -v オプション確認
   ├─ mrb_init_test_driver(mrb, verbose) でテストドライバ初期化
   │   ├─ t_print メソッド登録
   │   ├─ _str_match? メソッド登録
   │   ├─ Mrbtest モジュール定義
   │   ├─ FLOAT_TOLERANCE 定数設定
   │   └─ mrb_init_test_vformat() でvformat テスト支援登録
   ├─ mrb_load_irep(mrb, mrbtest_assert_irep) でアサーション読込
   ├─ mrbgemtest_init(mrb) で全gemテスト実行
   │   └─ 各gemのGENERATED_TMP_mrb_*_gem_test() を呼び出し
   ├─ eval_test(mrb) でreportメソッド呼び出し
   └─ mrb_close(mrb) で後処理

2. 各gemテスト実行（gem_test関数）
   ├─ mrb_open_core() で独立mrb_state生成
   ├─ GEMNAME定数設定
   ├─ アサーションirep読込
   ├─ 依存gemの初期化
   ├─ mrb_init_test_driver() でドライバ初期化
   ├─ カスタムテスト初期化（.cテストがある場合）
   ├─ テストirep読込・実行
   ├─ mrb_t_pass_result() で結果をメインmrb_stateに転送
   └─ mrb_close(mrb2)
```

### フローチャート

```mermaid
flowchart TD
    A[mrbtest起動] --> B[mrb_open]
    B --> C[テストドライバ初期化]
    C --> D[アサーションirep読込]
    D --> E[mrbgemtest_init]
    E --> F{各gemループ}
    F --> G[独立mrb_state生成]
    G --> H[依存gem初期化]
    H --> I[テストirep実行]
    I --> J[結果転送]
    J --> F
    F -->|完了| K[report呼出]
    K --> L{全テストpass?}
    L -->|Yes| M[EXIT_SUCCESS]
    L -->|No| N[EXIT_FAILURE]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-87-1 | 独立実行 | 各gemのテストは独立したmrb_stateで実行される | 常時 |
| BR-87-2 | 結果集約 | テスト結果（ok/ko/kill/warning/skip）はメインmrb_stateに転送 | 常時 |
| BR-87-3 | スキップ | skip_test?がtrueのgemはテストがスキップされる | gem設定依存 |
| BR-87-4 | 依存解決 | テスト用依存gem（add_test_dependency）も初期化される | テスト有効時 |

### 計算ロジック

特になし

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| EXIT_FAILURE | プロセス終了 | mrb_open_core()失敗 | エラー出力後exit |
| EXIT_FAILURE | プロセス終了 | テスト中に例外発生 | mrb_print_error + exit |
| EXIT_FAILURE | プロセス終了 | テスト失敗があった場合 | report()がfalse返却 |

### リトライ仕様

該当なし

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

GCアリーナのsave/restoreで各テスト実行後にメモリ状態を復元。

## パフォーマンス要件

特になし

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

特になし

## 備考

- mrbtest_assert_irepはtest/assert.rbをmrbcでコンパイルしたもの
- mrbgemtest_init関数はビルド時に自動生成される（mrbtest.c）
- テスト用のprint関数（t_print）はstdioがない環境でも動作する独自実装

---

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

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

### 推奨読解順序

#### Step 1: テストドライバを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | driver.c | `mrbgems/mruby-test/driver.c` | main関数（283-315行目）でテスト実行の全体フローを理解 |
| 1-2 | driver.c | `mrbgems/mruby-test/driver.c` | mrb_init_test_driver（213-241行目）でテスト環境初期化を確認 |

**読解のコツ**: driver.cの`main`関数がテスト実行の起点。`mrbgemtest_init`はビルド時に自動生成されるmrbtest.c内の関数で、全gemのテスト関数を順次呼び出す。

#### Step 2: テスト結果の転送を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | driver.c | `mrbgems/mruby-test/driver.c` | mrb_t_pass_result（243-281行目）で結果転送の仕組みを確認 |

**主要処理フロー**:
- **253-264行目**: $ok_test, $ko_test, $kill_test, $warning_test, $skip_testのグローバル変数を転送
- **268-280行目**: $assertsアサート結果配列を転送

#### Step 3: テストコード生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | mrbgem.rake | `mrbgems/mruby-test/mrbgem.rake` | gemテスト関数の自動生成ロジック（29-121行目）を確認 |

**主要処理フロー**:
- **67-68行目**: GENERATED_TMP_mrb_*_gem_test関数の生成開始
- **72-76行目**: 独立mrb_stateの生成とGEMNAME定数設定
- **85-89行目**: 依存gemの初期化
- **105-107行目**: テストirepの読み込みと実行
- **115行目**: mrb_t_pass_result()による結果転送

#### Step 4: パターンマッチを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | driver.c | `mrbgems/mruby-test/driver.c` | str_match_p（158-201行目）でglob風パターンマッチの実装を確認 |

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

```
main (driver.c)
    │
    ├─ mrb_open()
    ├─ mrb_init_test_driver()
    │     ├─ t_print 登録
    │     ├─ _str_match? 登録
    │     └─ mrb_init_test_vformat()
    │
    ├─ mrb_load_irep(mrbtest_assert_irep)
    │
    ├─ mrbgemtest_init() [自動生成]
    │     └─ 各gem: GENERATED_TMP_mrb_*_gem_test()
    │           ├─ mrb_open_core() [独立mrb_state]
    │           ├─ GENERATED_TMP_mrb_*_gem_init() [依存gem]
    │           ├─ mrb_load_irep(gem_test_irep_*)
    │           ├─ mrb_t_pass_result()
    │           └─ mrb_close(mrb2)
    │
    ├─ eval_test() → report()
    └─ mrb_close()
```

### データフロー図

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

test/*.rb ──mrbc──▶ gem_test_irep_* ──▶ mrb_load_irep
                                              │
test/*.c ──gcc──▶ mrb_*_gem_test() ──▶ テスト関数呼出
                                              │
                                    mrb_t_pass_result
                                              │
                                    ┌─────────▼─────────┐
                                    │ $ok_test, $ko_test │
                                    │ $kill_test, etc.   │
                                    └─────────┬─────────┘
                                              │
                                         report()
                                              │
                                    EXIT_SUCCESS / FAILURE
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| driver.c | `mrbgems/mruby-test/driver.c` | ソース | テストドライバ（main関数） |
| vformat.c | `mrbgems/mruby-test/vformat.c` | ソース | vformatテスト支援 |
| mrbgem.rake | `mrbgems/mruby-test/mrbgem.rake` | 設定 | テストコード自動生成・ビルド |
| assert.rb | `test/assert.rb` | テスト | アサーション関数定義 |
