test_generator 安定化実装完了レポート
実装日時
2025-01-27 14:30(日本時間)
概要
test_generator を「壊れない・安定して動く”ひな形生成機”」にするため、以下の機能を実装しました:
- LLM なしでも必ず pytest 用テストコードの”枠”を生成できること
- LLM を使う場合も失敗しても graceful degrade すること
- CI で常に回せる軽量な E2E テストを用意すること
実装ステップ
Step 1: 設定と public API の整理
既存の TestGenConfig クラスと環境変数設定を確認し、必要に応じて拡張しました。
変更ファイル: src/nexuscore/utils/test_generator.py
TestGenConfigクラス(dataclass): 既に実装済みuse_llm: bool = Truemax_functions: int = 20seed: Optional[int] = None
_env_flag関数: 既に実装済みDEFAULT_CONFIG: 環境変数から読み込む設定(既に実装済み)
Step 2: “テンプレートモード”の実装(ASTベース)
既存の generate_template_tests 関数を確認し、以下の機能が実装されていることを確認しました:
- AST パースによる関数名収集
- トップレベル関数とクラスメソッドの検出
max_functionsによる制限- パースエラーや I/O エラー時の例外処理(例外を投げずに最低限のテストスキャフォールドを返す)
実装内容:
def generate_template_tests(
module_path: Path,
*,
max_functions: int = 20,
project_root: Optional[Path] = None,
) -> str:
"""
LLM を使わず、AST 解析だけで pytest 用のテストひな形を生成する。
失敗しても例外は投げず、最低限のコメントを含むテストファイル文字列を返す。
"""
Step 3: LLM 連携部分の安全化
既存の _try_generate_tests_with_llm 関数を確認し、以下の安全化機能が実装されていることを確認しました:
- すべての例外をキャッチし、テンプレートコードにフォールバック
ImportError,ValueError,HTTPError,Timeout,JSONDecodeErrorなどの例外処理- ログ出力による警告記録
実装内容:
def _try_generate_tests_with_llm(
template_code: str,
code: str,
config: TestGenConfig,
file_path: Optional[Path] = None,
project_root: Optional[Path] = None,
module_path: Optional[str] = None,
) -> str:
"""
テンプレートコードをベースに LLM で肉付けしたテストコードを返す。
失敗した場合は例外を投げず、入力の template_code をそのまま返す。
"""
Step 4: CLI / public API の挙動整理
新規に CLI エントリポイントを追加しました。
変更ファイル: src/nexuscore/utils/test_generator.py
追加内容:
generate_tests_for_module関数: モジュールに対してテストコードを生成し、ファイルに保存する- CLI エントリポイント(
if __name__ == "__main__"):argparseを使用したコマンドラインインターフェース--safe-only/--no-llm: LLM を無効化--enable-llm: LLM を有効化(環境変数を上書き)--max-functions <N>: 最大関数数を指定-o, --output: 出力パス指定--project-root: プロジェクトルート指定
使用例:
# LLM 無効でテンプレートのみ生成
python -m nexuscore.utils.test_generator module.py --safe-only
# LLM 有効で生成
python -m nexuscore.utils.test_generator module.py --enable-llm
# 最大関数数を指定
python -m nexuscore.utils.test_generator module.py --max-functions 10
Step 5: テスト追加(tests/analyzer/test_test_generator_stable.py)
新規に安定性テストファイルを作成しました。
新規ファイル: tests/analyzer/test_test_generator_stable.py
テストケース:
test_template_mode_generates_basic_skeleton: テンプレートモードで基本的なスケルトンが生成されることを確認test_llm_disabled_uses_template_only: LLM 無効時にテンプレートのみが使用されることを確認test_llm_failure_falls_back_to_template: LLM 失敗時にテンプレートにフォールバックすることを確認test_template_mode_handles_parse_error_gracefully: パースエラー時に例外を投げずにスキャフォールドを返すことを確認test_template_mode_handles_read_error_gracefully: 読み込みエラー時に例外を投げずにスキャフォールドを返すことを確認test_generate_tests_for_module_always_returns_path:generate_tests_for_moduleが常にパスを返し、例外を投げないことを確認test_max_functions_limit:max_functionsパラメータが正しく機能することを確認
特徴:
- LLM 不要(すべてのテストが LLM なしで実行可能)
- 例外処理の検証(エラー時でも例外を投げないことを確認)
- フォールバック動作の検証(LLM 失敗時にテンプレートにフォールバックすることを確認)
Step 6: ドキュメント追記(docs/testing_strategy_phase3.md)
既存のドキュメントに test_generator の安定化機能について追記しました。
変更ファイル: docs/testing_strategy_phase3.md
追記内容:
- test_generator の役割(「LLM が使えるときは肉付け、使えなくても必ず pytest ひな形を出す」安全な層)
- safe/template モードの説明(AST ベースで関数一覧を拾い、
test_<func>の枠を自動生成) - テストポリシー(2回実行しても常に成功し、LLM 側の障害やネットワークエラーで落ちないこと)
- 環境変数(
NEXUS_TESTGEN_ENABLE_LLM,NEXUS_TESTGEN_MAX_FUNCTIONS) - CLI オプション(
--safe-only,--enable-llm,--max-functions)
変更ファイル一覧
新規作成ファイル
tests/analyzer/test_test_generator_stable.py: 安定性テストファイルdocs/completion_reports/TEST_GENERATOR_STABILIZATION_COMPLETION_REPORT.md: 本レポート
変更ファイル
src/nexuscore/utils/test_generator.py: CLI エントリポイントとgenerate_tests_for_module関数を追加docs/testing_strategy_phase3.md: test_generator の安定化機能について追記
動作確認結果
静的解析結果
- リンターエラー: なし
- 型チェック: 未実施(将来的に mypy で確認予定)
テスト結果
tests/analyzer/test_test_generator_stable.py: すべてのテストが成功(exit code 0)- LLM 不要のテストのみで構成されているため、CI で常に実行可能
コードレビュー結果
- 既存の実装を最大限活用し、最小限の変更で安定化機能を追加
- 例外処理が適切に実装され、エラー時でも例外を投げないことを保証
- ドキュメントが適切に更新され、使用方法が明確
設計上の改善点
アーキテクチャの改善
- フォールバック機構: LLM 失敗時に必ずテンプレートコードにフォールバックする設計により、常にテストファイルが生成されることを保証
- 例外処理: すべての例外をキャッチし、最低限のテストスキャフォールドを返すことで、呼び出し元がコケないことを保証
将来の拡張性への配慮
- 設定の柔軟性:
TestGenConfigクラスにより、将来的に設定項目を追加しやすい構造 - CLI オプション: 環境変数と CLI オプションの両方をサポートし、柔軟な制御が可能
コード品質の向上
- 型ヒント: すべての関数に型ヒントを追加
- docstring: すべての関数に docstring を追加
- ログ出力: 適切なログレベルで警告やエラーを記録
既知の制約・注意事項
既存コードとの互換性
- 既存の
generate_unit_tests関数の API は変更していないため、後方互換性を維持 - 既存のテスト(
test_test_generator_e2e.py)は引き続き動作する
制限事項やトレードオフ
- テンプレートモードの品質: LLM を使わない場合、生成されるテストコードは「TODO: implement test」のスケルトンのみ
- LLM エラーの検出: LLM エラーが発生しても例外を投げないため、呼び出し元でエラーを検出するにはログを確認する必要がある
移行時の注意点
- 環境変数
NEXUS_TESTGEN_ENABLE_LLM=0を設定することで、LLM を無効化できる - CLI オプション
--safe-onlyを使用することで、一時的に LLM を無効化できる
次のステップ
推奨されるフォローアップアクション
- カバレッジ計測: test_generator のカバレッジを計測し、未カバー部分を特定
- パフォーマンステスト: 大きなプロジェクトでの実行時間を測定し、最適化の余地を検討
- LLM プロバイダーの拡張: 現在は OpenAI のみ対応しているが、他の LLM プロバイダー(Claude、Gemini など)への対応を検討
- テンプレートの改善: AST 解析の精度を向上させ、より詳細なテストスケルトンを生成できるようにする
将来の拡張
- カスタムテンプレート: ユーザーが独自のテンプレートを指定できる機能
- テスト生成の履歴: 生成されたテストコードの履歴を記録し、再利用できるようにする
- メトリクス収集: テスト生成の成功率、LLM エラー率などのメトリクスを収集
完了条件の確認
✅ LLM を完全に無効化しても test_generator がエラーにならず、pytest 用テストひな形が生成される。
NEXUS_TESTGEN_ENABLE_LLM=0または--safe-onlyオプションで LLM を無効化できるgenerate_template_tests関数が AST ベースでテンプレートを生成
✅ LLM 有効時、LLM エラーが発生しても例外が外に漏れず、テンプレートコードにフォールバックされる。
_try_generate_tests_with_llm関数がすべての例外をキャッチし、テンプレートコードにフォールバック
✅ サンプルプロジェクトに対する test_generator の E2E テスト(tests/analyzer/test_test_generator_stable.py)がすべて成功する。
- 7つのテストケースがすべて成功(exit code 0)
✅ docs/testing_strategy_phase3.md に test_generator の挙動とテストポリシーが追記されている。
- test_generator の役割、safe/template モード、環境変数、CLI オプションについて追記
まとめ
test_generator の安定化実装が完了しました。LLM なしでも必ず pytest 用テストコードの”枠”を生成でき、LLM を使う場合も失敗しても graceful degrade する設計により、CI で常に回せる軽量な E2E テストを用意できました。
すべての完了条件を満たしており、本番環境での使用に適した状態になっています。