# バッチ設計書 20-create_test.py

## 概要

本ドキュメントは、Godotエンジンプロジェクトにおけるcreate_test.pyバッチ処理の設計仕様を定義する。このバッチは、単体テストファイルのひな形を自動生成し、開発者のテスト作成作業を効率化するPythonスクリプトである。

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

このバッチは、指定されたクラス名またはコンポーネント名に基づいて、Godotエンジンの単体テスト用ヘッダーファイルのひな形を生成するPythonスクリプトである。test_main.cppへの自動挿入機能もオプションで提供する。

**業務上の目的・背景**：Godotエンジンの品質向上には包括的な単体テストが不可欠である。しかし、テストファイルの作成は定型的な作業が多く、正しいファイル構造やGodotの著作権ヘッダーを手動で記述するのは非効率で、ミスの原因となる。このスクリプトにより、一貫したフォーマットのテストファイルを瞬時に生成でき、開発者はテストロジックの実装に集中できる。

**バッチの実行タイミング**：新しいクラスやコンポーネントのテストを作成する際に、開発者が手動で実行する。

**主要な処理内容**：
1. コマンドライン引数からクラス名とパスを取得
2. PascalCase名をsnake_caseに変換
3. テストファイルのパスを生成
4. ディレクトリが存在しない場合は作成
5. Godot著作権ヘッダー付きのテストひな形を生成
6. オプション（-i）でtest_main.cppにincludeディレクティブを自動挿入
7. clang-formatでincludeディレクティブを自動ソート

**前後の処理との関連**：生成されたテストファイルは開発者がテストロジックを実装し、ビルド時にtest_main.cppからインクルードされて実行される。

**影響範囲**：testsディレクトリに新しいテストヘッダーファイルが生成される。-iオプション使用時はtest_main.cppも更新される。

## バッチ種別

テスト・開発支援

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（テスト作成時） |
| 実行時刻 | 任意 |
| 実行曜日 | - |
| 実行日 | - |
| トリガー | 手動 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Python 3 | Python 3.x環境がインストールされていること |
| testsディレクトリ | スクリプトはtestsディレクトリから実行すること |
| clang-format（オプション） | -iオプション使用時、includeソートに使用 |

### 実行可否判定

同名のテストファイルが既に存在する場合はエラーを出力して終了する。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| name | 文字列 | Yes | - | テスト対象のクラス/コンポーネント名（PascalCase、例: MeshInstance3D） |
| path | 文字列 | No | "." | テストファイルの出力パス（testsフォルダからの相対パス） |
| -i, --invasive | フラグ | No | false | test_main.cppへの自動挿入を有効化 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| test_main.cpp | C++ | テストメイン関数（-iオプション時に更新） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| tests/{path}/test_{name_snake_case}.h | C++ヘッダー | テストファイルひな形 |
| tests/test_main.cpp | C++ | 更新されたメインファイル（-iオプション時） |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | test_{snake_case変換名}.h |
| 出力先 | tests/{path}/ |
| 文字コード | UTF-8 |
| 改行コード | LF |

## 処理フロー

### 処理シーケンス

```
1. 作業ディレクトリ移動
   └─ スクリプトのディレクトリ（tests）に移動
2. 引数解析
   └─ argparseでname, path, -iオプションを取得
3. 名前変換
   └─ PascalCaseからsnake_caseへ変換
   └─ 2D/3D/4Dを2d/3d/4dに事前変換（意図しない分割を防止）
4. ファイルパス生成
   └─ {path}/test_{name_snake_case}.hを生成
5. ディレクトリ作成
   └─ 必要に応じてディレクトリを作成
6. 既存ファイルチェック
   └─ 同名ファイルが存在する場合はエラー終了
7. テストファイル生成
   └─ Godot著作権ヘッダー、#pragma once、名前空間、サンプルテストケースを含むひな形を生成
8. 完了メッセージ出力
   └─ 絶対パスでファイル作成を通知
9. （オプション）test_main.cpp更新
   └─ -iオプション時、includeディレクティブを挿入
   └─ clang-formatでソート
10. （通常モード）手動挿入案内
    └─ includeディレクティブの追加方法を表示
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[引数解析]
    B --> C[PascalCase → snake_case変換]
    C --> D[ファイルパス生成]
    D --> E[ディレクトリ作成]
    E --> F{ファイル存在?}
    F -->|Yes| G[エラー出力・終了]
    F -->|No| H[テストファイル生成]
    H --> I{-iオプション?}
    I -->|Yes| J[test_main.cpp更新]
    J --> K[clang-format実行]
    K --> L[完了メッセージ]
    I -->|No| M[手動挿入案内表示]
    M --> L
    L --> N[バッチ終了]
```

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

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

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

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | ファイル存在エラー | 同名テストファイルが既に存在 | 別の名前を使用するか既存ファイルを削除 |
| - | clang-formatエラー | clang-formatコマンドが見つからない | clang-formatをインストール |
| - | 正規表現エラー | test_main.cppに適切な挿入位置が見つからない | 手動でincludeを追加 |

### リトライ仕様

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

### 障害時対応

バッチ失敗時は、以下を確認する：
1. 同名のテストファイルが存在しないか
2. testsディレクトリからスクリプトを実行しているか
3. -iオプション使用時はclang-formatがインストールされているか

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 該当なし（ファイル操作） |
| コミットタイミング | - |
| ロールバック条件 | - |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1テストファイル |
| 目標処理時間 | 1秒未満 |
| メモリ使用量上限 | 数MB以下 |

## 排他制御

同一ファイル名での同時実行は、最初の実行のみが成功し、後続はエラーとなる。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 情報ログ | パス出力時 | 相対パス（例: core/test_mesh_instance_3d.h） |
| 成功ログ | ファイル作成時 | "Test header file created:" + 絶対パス |
| エラーログ | ファイル存在時 | 'ERROR: The file "{path}" already exists.' |
| 案内ログ | -iなし時 | "Remember to #include the new test header..." |
| 情報ログ | -iあり時 | "Trying to insert include directive in test_main.cpp..." |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 終了コード | 0以外 | 手動確認 |

## 備考

- 名前の変換では2D/3D/4Dを2d/3d/4dに事前変換し、Node3DがNode_3_Dにならないようにしている
- 生成されるテストファイルには完全なGodot著作権ヘッダーが含まれる
- #pragma onceを使用（従来の#ifndefガードではない）
- 名前空間はTest{PascalCaseName}形式（例: TestMeshInstance3D）
- サンプルテストケースにはTODOコメントが含まれ、実装が必要なことを示す
- -iオプションは"Use with caution!"と警告されており、自動挿入が必ずしも正しい位置になるとは限らない
- test_main.cppのinclude挿入は`#include "tests.*\n`パターンにマッチする最初の位置の前に挿入される
- clang-formatが失敗した場合は手動ソートが必要という警告が表示される
