CR-NEXUS-037: External API smoke の仕様整合 - 完了レポート

実装日時

2025年12月23日

概要

目的

tests/api/test_external_api_smoke.py の失敗を解消し、external_api_smoke テストが安定して PASS する状態にする。

ゴール

  1. tests/api/test_external_api_smoke.py の全テストを PASS にする
  2. テスト内のモック不整合による 500 エラーを解消する
  3. テストの安定性を確保する

原則

  • テストコードのみを修正(実装コードは変更しない)
  • 既存のテストパターン(test_fastapi_project_runs.py)に合わせる
  • モックの整合性を保つ

実装ステップ

Step 1: 問題の特定

確認したファイル:

  • tests/api/test_external_api_smoke.py
  • src/nexuscore/api/routes/projects.py
  • tests/api/test_fastapi_project_runs.py

問題の原因:

  • external_api_smoke テストにおいて、test_get_latest_run_with_api_keytest_get_latest_run_without_runsRun.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

修正内容:

  1. test_get_latest_run_with_api_key:
    • patch("nexuscore.api.routes.projects.desc") を使用して desc() 関数をモック
    • mock_run.started_atmock_run.finished_at を datetime オブジェクトとして設定
    • test_fastapi_project_runs.py で確立されたパターンに合わせてクエリチェーンをモック
  2. 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_keytest_get_latest_run_without_runs が安定して動作している

設計上の改善点

テストの安定性向上

  • test_fastapi_project_runs.py で確立されたパターンを test_external_api_smoke.py にも適用
  • SQLAlchemy の desc() 関数に対するモックを統一することで、テストの一貫性が向上

既知の制約・注意事項

  • 実装コード(src/nexuscore/api/routes/projects.py)には変更を加えていない
  • テストコードのみの修正により、モックの整合性を保った

次のステップ

  • 他のテストファイルでも同様のパターン(desc() モック)が必要な場合は、統一することを推奨

This site uses Just the Docs, a documentation theme for Jekyll.