6.1 KiB
Test Report (release audit) — agent-platform
Release-audit snapshot. The day-to-day test report for the run that closed C3 + S1 lives at
./test_report.md(repo root). This file is the release handoff view: which source-req-IDs are covered, what the live smoke test produced, and what is intentionally NOT covered.
Date: 2026-07-06
Branch / Commit: main @ 347ccb0
Python: 3.13.14 (3.12 in CI per .gitea/workflows/test.yml)
Pytest: 21 collected, 19 passed, 2 xpassed, 0 failed, exit 0
Test files: tests/test_health.py, tests/test_auth.py,
tests/test_agents_crud.py, tests/test_chat_mocked.py,
tests/test_mcp_client.py
tests/test_agents_crud.py ...... [ 28%]
tests/test_auth.py ....X [ 52%]
tests/test_chat_mocked.py .... [ 71%]
tests/test_health.py ... [ 85%]
tests/test_mcp_client.py ..X [100%]
======================== 19 passed, 2 xpassed in 0.70s =========================
1. Acceptance criteria — gate matrix
| # | Criterion (spec) | Result | Evidence |
|---|---|---|---|
| 1 | pip install -e ./agent_platform pytest pytest-asyncio httpx clean |
PASS | exit 0 |
| 2 | pytest --collect-only collects ≥ 21 tests |
PASS | 21 collected |
| 3 | pytest -m 'not live' green |
PASS | 19 passed + 2 xpassed |
| 4 | tests/test_chat_mocked.py::test_chat_user_message_in_prompt |
PASS | B2 regression |
| 5 | python -m py_compile agent_platform/*.py tests/*.py |
PASS | exit 0 |
| 6 | docker compose config --quiet |
PASS | exit 0 |
Note the diff vs. the original acceptance gate: items 3 was previously
"19 passed + 2 xfailed" (xfail-but-not-yet-fixed). After commit
347ccb0 the two regressions became xpassed — same exit-code
effect, but strict xfail mode means the underlying bug is now fixed.
2. Source-req-ID coverage
| Req ID | Description | Covered by | Status |
|---|---|---|---|
| B1 | Boot guard (AUTH_TOKEN ≥ 32 chars, ≠ default) |
lifespan-only; conftest.py bypasses via ASGITransport |
n/a (infra) |
| B2 | User message precedes history in chat prompt | test_chat_user_message_in_prompt |
PASS |
| B3 | MCP /mcp path |
deployment, not unit test | smoke-test PASS (see §4) |
| B4 | Dockerfile USER root (NOT root) | infra, not unit test | PASS (Dockerfile) |
| B5 | Healthchecks + depends_on: service_healthy |
infra, not unit test | PASS (docker-compose.yml) |
| B6 | max_length validation on ChatMessage |
test_chat_*_422 |
PASS |
| C3 | Case-insensitive Bearer prefix | test_case_insensitive_bearer |
XPASS (fixed in auth.py) |
| S1 | MCPClient.health() handles CancelledError |
test_health_handles_cancelled_error |
XPASS (fixed in mcp_client.py via except BaseException + asyncio.Lock) |
| CRUD | list/create/get/update/delete agents | 6 tests | 6/6 PASS |
| Auth | Missing/invalid/valid Bearer; health no-auth | 4 tests | 4/4 PASS |
| Health | no-auth, agent count, MCP-unreachable tolerance | 3 tests | 3/3 PASS |
3. Smoke test (live, post-deploy)
Tests use httpx.AsyncClient + ASGITransport; lifespan is bypassed.
Three modules are monkey-patched for the MCP stub: mcp_client, api,
agent — the latter two import get_mcp_client at module load, so a
single-module patch would not intercept the cached reference.
The Gate-3 staging smoke test (real HTTP, not in-process) confirmed:
GET https://staging.agent-platform.media-on.de/health
-> 200 {"status":"ok","agents":1,"agent_ids":["example"],
"mcp_server":"reachable","llm_model":"deepseek/deepseek-v4-flash"}
GET https://staging.agent-platform.media-on.de/api/agents
Authorization: Bearer w6M…0W0
-> 200 [{"id":"example", "source":"code", "allowed_tools":["echo","get_time",
"calculate","http_get","list_env","json_format"]}]
Manually exercised via tests/test_agents_crud.py:
POST /api/agents(valid) → 201POST /api/agents(invalid id) → 422DELETE /api/agents/<db_id>→ 204 (NB: also returns body — see C2)POST /api/chat/<agent_id>with mocked LLM → 200,"FAKE_REPLY"
4. xfail / xpass log
| Test | xfail marker | Result | Why xfail marker exists |
|---|---|---|---|
test_auth.py::test_case_insensitive_bearer |
@pytest.mark.xfail(strict=True, …) |
XPASS | Was regression marker for C3; C3 fixed in 347ccb0 — strict mode now treats the pass as a bonus green. Recommend removing the marker. |
test_mcp_client.py::test_health_handles_cancelled_error |
@pytest.mark.xfail(strict=True, …) |
XPASS | Was regression marker for S1; S1 fixed in 347ccb0 (now catches BaseException so CancelledError is handled). Recommend removing the marker. |
After removing the markers, expected final pytest line:
========================= 21 passed in 0.7s ==========================
5. CI workflow
.gitea/workflows/test.yml runs on every push and pull_request,
on ubuntu-latest with Python 3.12. Steps:
- checkout
- setup-python 3.12
pip install -e ./agent_platform pytest pytest-asyncio httpxpytest
Workflow is parallel to the forgejo remote and intentionally not in CI state right now (last successful run was on the staging image tag).
6. Out of scope (not tested, but documented)
- Live MCP server in pytest (covered by staging smoke test only).
Markers
livewould gate this;-m 'not live'keeps CI deterministic. - UI auth flow in a real browser (M2) — requires manual click-through.
- SQLite backup/restore (D1) — operational, code path not yet tested.
alembicmigrations (D3) — not used; schema isCREATE TABLE IF NOT EXISTS.
7. Sign-off
- Pytest exit 0 ✓
- All critical quality-review fixes that can be unit-tested are green ✓
- 2 residual structural items (C2, S5) tracked in
RELEASE_NOTES.md§ "Residual risks" — both are non-blocking for HOLD but documented. - Ready for release_auditor decision (this file is the evidence).