コンテンツにスキップ

AI Read API(mcp-api)— テストケース

このページは guinness-ai-v2 の apps/mcp-api/ のテスト計画である。io-definition.md のすべての行 — エンドポイント、クエリパラメータ、DocumentDB オペレーション、エラークラス — は、ここで少なくとも 1 つのテストケースにトレースされなければならない。コントラクト条項にテストがない場合、それが最優先で修正すべきバグである。

規約. テスト ID は AM-<layer>-<NN> に従う。レイヤー: U(ユニット、I/O なし)、C(integration、実際の DocumentDB testcontainer、モック認証)、E(E2E、実際のクラウド)。各ケースは Given / When / Then を明示する。


テストレイヤーとツール

レイヤー スコープ ツール
Unit (U) 純粋関数: 認証検証、クエリパラメータパース、DocumentDB フィルタビルダー、レスポンスビルダー pytest、ネットワークなし。DocumentDB / httpx は境界でモック
Integration (C) 実際の testcontainer Mongo(DocumentDB API 互換 mongo:7 イメージ)+ デフォルトで有効なトークンを使用する完全リクエストライフサイクル pytest、testcontainers[mongodb]、httpx TestClient。Docker が必要
End-to-end (E) 実際の MCP Server → AI Read API → DocumentDB ラウンドトリップ(dev 環境) 手動 / スモークのみ

共有フィクスチャ

フィクスチャ 提供するもの 使用テスト
valid_token テスト用の AI_SERVICE_TOKEN の値 U, C
design_doc(**overrides) 整形された DocumentDB design ドキュメント U, C
code_doc(**overrides) _id、name、source_code、visual.metadata.image_url を持つ整形された DocumentDB code ドキュメント U, C
seed_design(collection, doc) design ドキュメントを testcontainer Mongo に挿入 C
seed_design_batch(collection, count, project_id) 指定された project_id で N 件の design ドキュメントを挿入 C
seed_code_batch(collection, count, project_id) 指定された project_id で N 件の code ドキュメントを挿入 C

カバレッジマトリックス

ハッピーパス 失敗パス 冪等性
認証(トークン) AM-U-01 AM-U-02, AM-U-03 —
パラメータバリデーション AM-U-04 AM-U-05 —
GET /internal/designs/{design_id} AM-U-06, AM-C-01 AM-C-02 AM-C-05
GET /internal/designs AM-U-07, AM-C-03 — AM-C-05
GET /internal/code AM-U-08, AM-C-04 — AM-C-05
GET /internal/code/{code_id} AM-U-09, AM-C-06 AM-C-07 AM-C-05
ページネーション (limit/offset) AM-U-10 — —
無効な limit(負の値 / 非整数) AM-U-11 — —
空の list 結果 AM-C-08 — —
DocumentDB エラー — AM-C-09 —

ユニット (U) テスト

ネットワークなし。純粋な Python。

AM-U-01 — 有効な X-AI-Service-Token が受理

  • Given 設定された環境変数値に一致する X-AI-Service-Token を持つリクエスト。
  • When 認証ミドルウェアがトークンを検証。
  • Then 検証が通過(401 がスローされない)。

AM-U-02 — X-AI-Service-Token なし → 401

  • Given X-AI-Service-Token ヘッダーのないリクエスト。
  • When 認証ミドルウェアが検証。
  • Then HTTP 401、{ ok: false, error: { code: "UNAUTHORIZED" } }。

AM-U-03 — 誤ったトークン → 401

  • Given 環境変数値に一致しない X-AI-Service-Token を持つリクエスト。
  • When 認証ミドルウェアが検証。
  • Then HTTP 401、{ ok: false, error: { code: "UNAUTHORIZED" } }。
  • And 比較がタイミングセーフ(実装が hmac.compare_digest または同等を使用していることを検証 — ショートサーキットなし)。

AM-U-04 — path で route を選択

  • Given /internal/designs, /internal/designs/{design_id}, /internal/code, /internal/code/{code_id}。
  • When ルータが handler を決定。
  • Then list-designs, get-design-detail, list-code, get-code-detail をそれぞれ選択する。

AM-U-05 — list endpoint に project_id がない → 400

  • Given project_id なしの GET /internal/designs または GET /internal/code。
  • When ルータがパラメータを検証。
  • Then HTTP 400、{ ok: false, error: { code: "BAD_REQUEST" } }。

AM-U-06 — design_id クエリが正しい DocumentDB フィルタを構築

  • Given design_id = "1_abc_def"。
  • When リポジトリがクエリを構築。
  • Then フィルタは {"_id": "1_abc_def"}。
  • And オペレーションは find_one(find ではない)。

AM-U-07 — list-designs がプロジェクション付きの正しいフィルタを構築

  • Given project_id = 42、organization_id = 1、limit = 10、offset = 5。
  • When リポジトリが design list query を構築。
  • Then フィルタは {"project_id": 42, "organization_id": 1}。
  • And projection はすべての vector_embedding field を除外する。
  • And カーソルに .skip(5).limit(10) がある。

AM-U-08 — list-code がプロジェクション付きの正しいフィルタを構築

  • Given project_id = 42、organization_id = 1、limit = 10、offset = 5。
  • When リポジトリが code list query を構築。
  • Then フィルタは {"project_id": 42}。
  • And projection は _id, organization_id, project_id, name, type, based_on, visual.metadata.image_url を含む。
  • And source_code, css_code, すべての vector_embedding field を除外する。
  • And カーソルに .skip(5).limit(10) がある。

AM-U-09 — code detail が正しい DocumentDB filter を構築

  • Given code_id = "660e8400-e29b-41d4-a716-446655440001"。
  • When リポジトリが query を構築。
  • Then filter は {"_id": "660e8400-e29b-41d4-a716-446655440001"}。
  • And operation は find_one。
  • And projection はすべての vector_embedding field を除外する。

AM-U-10 — limit/offset が正しく適用される

  • パラメータ化:
  • limit なし → デフォルト 20。
  • limit = 200 → 100 にキャップ。
  • offset なし → デフォルト 0。
  • offset = 50 → .skip(50)。
  • Then 正しい値が DocumentDB カーソルに渡される。

AM-U-11 — 無効な limit はデフォルトにフォールバック

  • パラメータ化:
  • limit = -1 → デフォルト 20 にフォールバック。
  • limit = 0 → デフォルト 20 にフォールバック。
  • limit = "abc"(非整数文字列)→ デフォルト 20 にフォールバック。
  • Then DocumentDB カーソルに .limit(20) が渡される。
  • And エラーは返されない — 無効な値は I/O コントラクトに従い暗黙に修正される。

AM-U-12 — offset が合計件数を超過 → 空のページ

  • Given project_id = 42 で code コレクションに 5 件のドキュメントがある。
  • When GET /internal/code?project_id=42&offset=100。
  • Then HTTP 200。
  • { ok: true, data: { project_id: 42, total: 5, items: [] } }。
  • And total は実際の件数(5)を反映し、0 ではない。

Integration (C) テスト

実際の testcontainer Mongo(DocumentDB API 互換)。認証はモック(デフォルトで有効なトークン)。

AM-C-01 — design_id で GET — ドキュメントが見つかる

  • Given:
  • design コレクションに _id = "1_abc_def"、project_id = 42、name = "Login Screen"、visual.metadata.image_url = "s3://..." のドキュメントがある。
  • 有効な認証トークン。
  • When GET /internal/designs/1_abc_def。
  • Then:
  • HTTP 200。
  • { ok: true, data: { id: "1_abc_def", project_id: 42, name: "Login Screen", image_url: "s3://..." } }。
  • data に vector_embedding やその他の内部フィールドが含まれていない。

AM-C-02 — design_id で GET — ドキュメントが見つからない

  • Given:
  • design コレクションに _id = "nonexistent" のドキュメントがない。
  • 有効な認証トークン。
  • When GET /internal/designs/nonexistent。
  • Then:
  • HTTP 404。
  • { ok: false, data: null, error: { code: "NOT_FOUND", message: "Design not found" } }。

AM-C-03 — project_id で design list

  • Given:
  • design コレクションに project_id = 42 のドキュメントが 25 件ある。
  • 有効な認証トークン。
  • When GET /internal/designs?project_id=42&limit=10&offset=5。
  • Then:
  • HTTP 200。
  • { ok: true, data: { project_id: 42, total: 25, items: [...] } }。
  • vector_embedding フィールドの漏洩がない。

AM-C-04 — project_id で code list

  • Given:
  • code コレクションに project_id = 42 のドキュメントが 25 件ある。
  • 有効な認証トークン。
  • When GET /internal/code?project_id=42&organization_id=1&limit=10&offset=5。
  • Then:
  • HTTP 200。
  • { ok: true, data: { project_id: 42, total: 25, items: [...] } }。
  • items 配列が正確に 10 アイテム。
  • 各 code item に id, project_id, organization_id, name, image_url がある。
  • code list item は source_code / css_code を含まない。
  • vector_embedding フィールドの漏洩がない。

AM-C-05 — 同一リクエストの繰り返しが同じデータを返す

  • Given AM-C-01 のセットアップ(design が見つかる)。
  • When 同じ GET /internal/designs/1_abc_def が 2 回呼び出される。
  • Then 両方のレスポンスが同一(ステートレス、冪等)。

AM-C-06 — code detail が見つかる

  • Given code コレクションに _id = "660e8400-e29b-41d4-a716-446655440001" のドキュメントがある。
  • When GET /internal/code/660e8400-e29b-41d4-a716-446655440001。
  • Then HTTP 200。data.code は source_code を含み、vector_embedding を含まない。

AM-C-07 — code detail が見つからない

  • Given _id = "missing" の code document がない。
  • When GET /internal/code/missing。
  • Then HTTP 404、{ ok: false, data: null, error: { code: "NOT_FOUND" } }。

AM-C-08 — list endpoint のコレクションが空

  • Given:
  • code コレクションに project_id = 99 のドキュメントがない。
  • 有効な認証トークン。
  • When GET /internal/code?project_id=99&organization_id=1。
  • Then:
  • HTTP 200(404 ではない — 空の結果はエラーではない)。
  • { ok: true, data: { project_id: 99, total: 0, items: [] } }。

AM-C-09 — DocumentDB 接続エラー

  • Given:
  • Mongo testcontainer が停止 / 一時停止(接続失敗をシミュレート)。
  • 有効な認証トークン。
  • When GET /internal/designs/1_abc_def。
  • Then:
  • HTTP 500。
  • { ok: false, data: null, error: { code: "INTERNAL_ERROR", message: "..." } }。
  • ERROR レベルでエラーがログに記録される(ai-mcp.query.failed)。

E2E (E) テスト

スモークテストセット。実際のサービスに対して手動で実行。

AM-E-01 — MCP Server → AI Read API ラウンドトリップ

  • Given 実際の AI_SERVICE_URL と AI_SERVICE_TOKEN で dev に対して設定された MCP Server。
  • When MCP クライアントが既知の ID で list-designs, list-code, get-design-detail, get-code-detail を呼び出す。
  • Then 30 秒以内に:
  • MCP レスポンスに DocumentDB のdesign/code dataが含まれる。
  • CloudWatch に表示: ai-mcp.request.received → ai-mcp.query.completed → ai-mcp.response.sent。
  • 401 または 500 エラーがない。

横断チェック

該当するテスト全体で成立すべき条件。独立したテスト行ではなく、上記のテストのレビュー時や実行時に検証する。

  • Postgres 接続が開かれない。 Postgres ドライバに到達できない状態(またはガード環境変数を設定)でテストを実行。誤ったドライバインポートが即座に表面化。
  • レスポンスが常に { ok, data, error } エンベロープに従う。 全テストでエンベロープ構造を表明 — エラーレスポンスも準拠する必要がある。
  • 認証がタイミングセーフ。 実装が hmac.compare_digest または同等を使用していることを検証 — シークレット文字列に == を使用しない。
  • 全テストで DocumentDB 書き込みがない。 各テストの前後で collection.count_documents() が変更されていないことを表明。
  • vector_embedding フィールドの漏洩がない。 レスポンスデータを表明する全テストで、出力に vector_embedding キーが含まれていないことを検証。
  • detail route は total や items 配列を返さない。 list route は page list、detail route は { design: ... } または { code: ... } を返す。
  • エラーレスポンスに data が含まれない。 ok = false の場合、data は null でなければならない(省略でも空オブジェクトでもなく)。

意図的なスコープ外

将来のテストが正しいバケットに配置されるよう、明示的に列挙。

  • MCP Server の認証とツールルーティング。 mcp/ テストケース設計が管轄。この API は独自の X-AI-Service-Token のみを検証。
  • DocumentDB インデックス管理。 packages/models/ が管轄。この API はインデックスが存在することを前提とする。
  • SQS とのやり取り。 この API は HTTP のみ。SQS は関与しない。
  • CORS / CloudFront 設定。 インフラレベル。この API は VPC 内部のみ。
  • レートリミット / スロットリング。 TBD。仕様化されるまでテストなし。
  • generated-code endpoint。 将来の endpoint。まだ contract にない。
  • データ移行またはシード。 運用上の懸念。テストフィクスチャは独自のデータを管理。

関連情報

  • I/O 定義 — これらのテストが担保するコントラクト
  • 概要 — リクエストフロー、DocumentDB クエリパターン、認証の詳細