ワンクリックで
api-tester
Run, maintain, and extend the duck-demo API contract test suite (REST + MCP tools).
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Run, maintain, and extend the duck-demo API contract test suite (REST + MCP tools).
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
You are a QC inspector agent for a rubber duck factory. You look at batch photos, run quality control inspections, and manage dispositions.
You are an mcp expert, from prompting to mcp tool definition, documentation and debugging.
Connect to and interact with the MyForterro API (authentication, tenant management, AI agents, invoicing, inference).
You are a UX expert, that values consistency above all
Analyse data in the demo SQLite database using SQL queries
| name | api-tester |
| description | Run, maintain, and extend the duck-demo API contract test suite (REST + MCP tools). |
Manage the pytest-based contract test suite that validates all REST API endpoints and MCP tool interfaces against a minimal seed database.
tests/
conftest.py # Fixtures: temp DB, seed data, Starlette TestClient, FastMCP instance
seed_test_data.py # Minimal deterministic dataset (~25 rows across all tables)
contract_helpers.py # Shape-checking utilities (assert_shape, ANY, AnyOf, ListOf, Optional)
test_rest_system.py # REST: /api/health, simulation, spotlight
test_rest_customers.py # REST: /api/customers
test_rest_catalog.py # REST: /api/items
test_rest_stock.py # REST: /api/stock
test_rest_sales.py # REST: /api/sales-orders, quote-options
test_rest_shipments.py # REST: /api/shipments
test_rest_production.py # REST: /api/production-orders, work-centers
test_rest_reference.py # REST: /api/recipes, suppliers, purchase-orders
test_rest_documents.py # REST: /api/emails, quotes, invoices
test_rest_activity.py # REST: /api/activity-log, dashboard
test_mcp_shared.py # MCP: shared tools (user, simulation, stats, catalog, inventory, activity)
test_mcp_sales.py # MCP: sales tools (CRM, orders, quotes, invoices, messaging, logistics)
test_mcp_production.py # MCP: production tools (orders, work centers)
source venv/bin/activate
# Run all tests
pytest
# Run only REST tests
pytest -m rest
# Run only MCP tests
pytest -m mcp
# Run a specific test file
pytest tests/test_rest_sales.py
# Run with verbose output
pytest -v
# Run a single test
pytest tests/test_rest_sales.py::test_get_sales_order_detail -v
Tests check response shape (required keys, value types, list non-emptiness), not exact values. This means:
assert_shape helperfrom tests.contract_helpers import assert_shape, AnyOf, ListOf, Optional, ANY
# Check that data has the right structure
assert_shape(data, {
"id": str, # must be a string
"total": AnyOf(int, float), # int or float
"lines": ListOf({"sku": str}), # list of dicts each with "sku" key
"notes": Optional(str), # may be missing
"metadata": ANY, # any value, just must exist
})
| Layer | How it works | What it tests |
|---|---|---|
| REST | rest_client.get("/api/...") via Starlette TestClient | HTTP status, JSON shape, query param parsing |
| MCP | tool.fn(...) direct Python call | Tool params, service integration, return shape |
REST tests go through the full HTTP stack (Starlette routing, CORS, serialization). MCP tests skip JSON-RPC transport but exercise the complete tool → service → DB path.
The DB and test client are created once per session (not per test), making the suite fast. Tests are read-only against seed data — no test modifies the database.
tests/seed_test_data.py contains a small, static dataset with known IDs:
CUST-0101, CUST-0102ITEM-PVC, ITEM-YELLOW-DYE, ITEM-BOX-SMALL, ITEM-CLASSIC-10RCP-CLASSIC-10SO-T001 (confirmed, for CUST-0101)QUO-T001 (accepted)SHIP-T001MO-T001PO-T001INV-T001 (issued)EMAIL-T001test_rest_{domain}.py.def test_my_new_endpoint(rest_client):
resp = rest_client.get("/api/my-endpoint", params={"key": "value"})
assert resp.status_code == 200
data = resp.json()
assert_shape(data, {"expected_key": str})
seed_test_data.py.test_mcp_{domain}.py.def _call(mcp_app, tool_name, **kwargs):
tool = mcp_app._tool_manager._tools[tool_name]
return tool.fn(**kwargs)
def test_my_new_tool(mcp_app):
result = _call(mcp_app, "my_tool_name", param1="value")
assert isinstance(result, dict)
assert_shape(result, {"expected_key": str})
Mutating MCP tools return a CallToolResult (confirmation response), not a dict. Test the shape of the confirmation metadata:
def test_my_mutating_tool(mcp_app):
result = _call(mcp_app, "my_mutating_tool", param="value")
# Mutating tools return CallToolResult with structuredContent
assert hasattr(result, 'structuredContent')
metadata = result.structuredContent
assert metadata["original_tool"] == "my_mutating_tool"
When the schema changes:
tests/seed_test_data.py to add/remove/rename columns.TABLE_DATA insertion order (respects FK dependencies).pytest to verify nothing else broke.SO-T001, CUST-0101, etc.2025-08-01T08:00:00.@pytest.mark.rest, MCP tests with @pytest.mark.mcp.