Files
gomag-vending/api/tests/qa/test_qa_api_health.py
Claude Agent 419464a62c feat: add CI/CD testing infrastructure with test.sh orchestrator
Complete testing system: pyproject.toml (pytest markers), test.sh
orchestrator with auto app start/stop and colorful summary,
pre-push hook, Gitea Actions workflow.

New QA tests: API health (7 endpoints), responsive (3 viewports),
log monitoring (ERROR/ORA-/Traceback detection), real GoMag sync,
PL/SQL package validation, smoke prod (read-only).

Converted test_app_basic.py and test_integration.py to pytest.
Added pytestmark to all existing tests (unit/e2e/oracle).
E2E conftest upgraded: console error collector, screenshot on
failure, auto-detect live app on :5003.

Usage: ./test.sh ci (30s) | ./test.sh full (2-3min)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 10:40:25 +00:00

88 lines
2.1 KiB
Python

"""QA tests for API endpoint health and basic contract validation."""
import time
import urllib.request
import pytest
import httpx
pytestmark = pytest.mark.qa
ENDPOINTS = [
"/health",
"/api/dashboard/orders",
"/api/sync/status",
"/api/sync/history",
"/api/validate/missing-skus",
"/api/mappings",
"/api/settings",
]
@pytest.fixture(scope="session")
def client(base_url):
"""Create httpx client; skip all if app is not reachable."""
try:
urllib.request.urlopen(f"{base_url}/health", timeout=3)
except Exception:
pytest.skip(f"App not reachable at {base_url}")
with httpx.Client(base_url=base_url, timeout=10.0) as c:
yield c
def test_health(client):
r = client.get("/health")
assert r.status_code == 200
data = r.json()
assert "oracle" in data
assert "sqlite" in data
def test_dashboard_orders(client):
r = client.get("/api/dashboard/orders")
assert r.status_code == 200
data = r.json()
assert "orders" in data
assert "counts" in data
def test_sync_status(client):
r = client.get("/api/sync/status")
assert r.status_code == 200
data = r.json()
assert "status" in data
def test_sync_history(client):
r = client.get("/api/sync/history")
assert r.status_code == 200
data = r.json()
assert "runs" in data
assert isinstance(data["runs"], list)
def test_missing_skus(client):
r = client.get("/api/validate/missing-skus")
assert r.status_code == 200
data = r.json()
assert "missing_skus" in data
def test_mappings(client):
r = client.get("/api/mappings")
assert r.status_code == 200
data = r.json()
assert "mappings" in data
def test_settings(client):
r = client.get("/api/settings")
assert r.status_code == 200
assert isinstance(r.json(), dict)
@pytest.mark.parametrize("endpoint", ENDPOINTS)
def test_response_time(client, endpoint):
start = time.monotonic()
client.get(endpoint)
elapsed = time.monotonic() - start
assert elapsed < 5.0, f"{endpoint} took {elapsed:.2f}s (limit: 5s)"