T10: Monitoring, Performance, Documentation & Environment Config — 38 tests, ruff clean, docs OK
- Extended health endpoint: DB+Redis+Storage+Worker checks with degraded status - Prometheus metrics endpoint: admin-only, text/plain format - Metrics: http_requests_total, db_pool_connections, arq_jobs_total - Structured JSON logging (structlog): timestamp, level, method, path, status, duration_ms, tenant_id - Performance: page_size max 100 enforced (422), streaming CSV export (StreamingResponse) - Scripts: seed_perf_data.py, check_indexes.py - Docs: admin-guide.md (Deploy, Backup, Restore, Env-Vars, Troubleshooting), api-overview.md - README updated: prod setup, API section, env profiles, admin-guide link - .env.example: added SECRET_KEY, STORAGE_PATH, SMTP_* vars - 38 new tests, full regression 564/564 pass (0 failures) - Ruff: all checks passed
This commit is contained in:
+44
-4
@@ -1,4 +1,4 @@
|
||||
"""Health endpoint test — AC 18."""
|
||||
"""Health endpoint test — AC1-2: Extended health check with DB, Redis, storage, worker."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -8,12 +8,52 @@ from httpx import AsyncClient
|
||||
|
||||
@pytest.mark.asyncio
|
||||
class TestHealth:
|
||||
"""AC 18: GET /api/v1/health -> 200 without auth."""
|
||||
"""AC1: GET /api/v1/health -> 200 without auth, with extended checks."""
|
||||
|
||||
async def test_health_returns_200_without_auth(self, client: AsyncClient):
|
||||
"""AC 18: GET /api/v1/health -> 200 without auth."""
|
||||
"""AC1: GET /api/v1/health -> 200 without auth."""
|
||||
resp = await client.get("/api/v1/health")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["status"] == "ok"
|
||||
assert "status" in data
|
||||
assert "version" in data
|
||||
assert "checks" in data
|
||||
|
||||
async def test_health_has_database_check(self, client: AsyncClient):
|
||||
"""AC1: Health response includes checks.database."""
|
||||
resp = await client.get("/api/v1/health")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert "database" in data["checks"]
|
||||
assert "status" in data["checks"]["database"]
|
||||
|
||||
async def test_health_has_redis_check(self, client: AsyncClient):
|
||||
"""AC1: Health response includes checks.redis."""
|
||||
resp = await client.get("/api/v1/health")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert "redis" in data["checks"]
|
||||
assert "status" in data["checks"]["redis"]
|
||||
|
||||
async def test_health_has_storage_check(self, client: AsyncClient):
|
||||
"""AC1: Health response includes checks.storage."""
|
||||
resp = await client.get("/api/v1/health")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert "storage" in data["checks"]
|
||||
assert "status" in data["checks"]["storage"]
|
||||
|
||||
async def test_health_has_worker_check(self, client: AsyncClient):
|
||||
"""AC1: Health response includes checks.worker."""
|
||||
resp = await client.get("/api/v1/health")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert "worker" in data["checks"]
|
||||
assert "status" in data["checks"]["worker"]
|
||||
|
||||
async def test_health_status_is_valid_value(self, client: AsyncClient):
|
||||
"""Health status should be 'healthy' or 'degraded'."""
|
||||
resp = await client.get("/api/v1/health")
|
||||
assert resp.status_code == 200
|
||||
data = resp.json()
|
||||
assert data["status"] in ("healthy", "degraded")
|
||||
|
||||
Reference in New Issue
Block a user