CR-NEXUS-037: External API smoke の仕様整合 - 完了レポート
実装日時
2025年12月23日
概要
目的
tests/api/test_external_api_smoke.py の失敗を解消し、external_api_smoke テストが安定して PASS する状態にする。
ゴール
tests/api/test_external_api_smoke.pyの全テストを PASS にする- テスト内のモック不整合による 500 エラーを解消する
- テストの安定性を確保する
原則
- テストコードのみを修正(実装コードは変更しない)
- 既存のテストパターン(test_fastapi_project_runs.py)に合わせる
- モックの整合性を保つ
実装ステップ
Step 1: 問題の特定
確認したファイル:
tests/api/test_external_api_smoke.pysrc/nexuscore/api/routes/projects.pytests/api/test_fastapi_project_runs.py
問題の原因:
- external_api_smoke テストにおいて、
test_get_latest_run_with_api_keyとtest_get_latest_run_without_runsでRun.started_atが MagicMock のままorder_by(desc(Run.started_at))に渡されていた - SQLAlchemy の
desc()関数が MagicMock オブジェクトを処理できず、ArgumentErrorが発生(”GROUP BY / OF / etc. expression expected, got") - その結果、500 エラーが返されていた
- この問題は
/api/v1/projects/{project_id}/runs/latestエンドポイントのテストで発生していた
Step 2: モックの修正
変更ファイル:
tests/api/test_external_api_smoke.py
修正内容:
test_get_latest_run_with_api_key:patch("nexuscore.api.routes.projects.desc")を使用してdesc()関数をモックmock_run.started_atとmock_run.finished_atを datetime オブジェクトとして設定test_fastapi_project_runs.pyで確立されたパターンに合わせてクエリチェーンをモック
test_get_latest_run_without_runs:- 同様に
desc()関数をモック - Run が見つからない場合のクエリチェーンを適切にモック
- 同様に
修正の意図:
Run.started_atが MagicMock のままorder_by(desc(...))に渡されることによる SQLAlchemy 式評価エラーを回避desc()をモックすることで、実際の SQLAlchemy Column オブジェクトを渡すことなく、クエリチェーンをモック可能にする
実装理由:
test_fastapi_project_runs.pyで既に確立されているパターンに合わせる- SQLAlchemy の
desc()関数が MagicMock を処理できない問題を回避する
変更ファイル一覧
変更ファイル
tests/api/test_external_api_smoke.py-desc()モックの追加、datetime 属性の補完
動作確認結果
テスト結果
実行コマンド:
python -m pytest tests/api/test_external_api_smoke.py -q
結果: 7 passed
- ✅
test_get_projects_requires_api_key: PASS - ✅
test_get_projects_with_api_key: PASS - ✅
test_post_run_requires_api_key: PASS - ✅
test_post_run_with_api_key: PASS - ✅
test_get_latest_run_requires_api_key: PASS - ✅
test_get_latest_run_with_api_key: PASS - ✅
test_get_latest_run_without_runs: PASS
確認項目:
- ✅ external_api_smoke テストの全テストが PASS している
- ✅
desc()モックが正しく動作している - ✅ SQLAlchemy の例外が発生しなくなっている(500 エラーが解消された)
- ✅
test_get_latest_run_with_api_keyとtest_get_latest_run_without_runsが安定して動作している
設計上の改善点
テストの安定性向上
test_fastapi_project_runs.pyで確立されたパターンをtest_external_api_smoke.pyにも適用- SQLAlchemy の
desc()関数に対するモックを統一することで、テストの一貫性が向上
既知の制約・注意事項
- 実装コード(
src/nexuscore/api/routes/projects.py)には変更を加えていない - テストコードのみの修正により、モックの整合性を保った
次のステップ
- 他のテストファイルでも同様のパターン(
desc()モック)が必要な場合は、統一することを推奨