Files
ai-safety-platform/tests/test_health.py
T
baozaotumao2025 14722be770 first commit
2026-07-18 21:00:26 +08:00

118 lines
5.2 KiB
Python

from fastapi.testclient import TestClient
from app.main import app
def test_health():
client = TestClient(app)
response = client.get("/api/v1/health")
assert response.status_code == 200
assert response.json()["status"] == "ok"
def test_openapi_available():
client = TestClient(app)
response = client.get("/openapi.json")
assert response.status_code == 200
assert "/api/v1/health" in response.json()["paths"]
assert "/api/v1/test-plans" not in response.json()["paths"]
def test_openapi_declares_bearer_authorization_for_protected_operations():
schema = TestClient(app).get("/openapi.json").json()
bearer = schema["components"]["securitySchemes"]["BearerAuth"]
assert bearer == {"type": "http", "scheme": "bearer"}
assert schema["paths"]["/api/v1/providers/{provider_id}/check"]["post"]["security"] == [
{"BearerAuth": []}
]
assert schema["paths"]["/api/v1/auth/users"]["get"]["security"] == [{"BearerAuth": []}]
assert schema["paths"]["/api/v1/auth/users/{user_id}"]["delete"]["security"] == [
{"BearerAuth": []}
]
assert schema["paths"]["/api/v1/auth/me"]["get"]["security"] == [{"BearerAuth": []}]
assert schema["paths"]["/api/v1/auth/password"]["patch"]["security"] == [{"BearerAuth": []}]
assert "security" not in schema["paths"]["/api/v1/health"]["get"]
assert "security" not in schema["paths"]["/api/v1/auth/login"]["post"]
def test_self_service_auth_openapi_is_documented():
schema = TestClient(app).get("/openapi.json").json()
assert "is_admin" in schema["components"]["schemas"]["UserResponse"]["properties"]
change = schema["components"]["schemas"]["ChangePasswordRequest"]
assert set(change["required"]) == {"current_password", "new_password"}
assert "重新登录" in schema["paths"]["/api/v1/auth/password"]["patch"]["description"]
def test_provider_check_openapi_is_documented():
schema = TestClient(app).get("/openapi.json").json()
operation = schema["paths"]["/api/v1/providers/{provider_id}/check"]["post"]
assert "/api/v1/providers/check" not in schema["paths"]
assert "模型提供商" in operation["summary"]
assert (
operation["responses"]["502"]["content"]["application/json"]["schema"]["$ref"]
== "#/components/schemas/ErrorResponse"
)
provider = operation["parameters"][0]["schema"]
assert provider["enum"] == ["target", "judge"]
def test_capability_probe_is_internal_to_runs():
schema = TestClient(app).get("/openapi.json").json()
assert "/api/v1/capabilities/probe" not in schema["paths"]
assert "能力探测" in schema["paths"]["/api/v1/runs"]["post"]["description"]
assert {"get", "post"} <= set(schema["paths"]["/api/v1/runs"])
assert {"get", "patch", "delete"} <= set(schema["paths"]["/api/v1/runs/{run_id}"])
assert "/api/v1/runs/{run_id}/retry-errors" in schema["paths"]
assert "/api/v1/runs/{run_id}/results/{execution_id}/retry" in schema["paths"]
def test_start_run_openapi_explains_usage():
schema = TestClient(app).get("/openapi.json").json()
operation = schema["paths"]["/api/v1/runs"]["post"]
response = schema["components"]["schemas"]["RunResponse"]
assert '"profile": "smoke"' in operation["description"]
assert "单轮、多轮、工具和图片各选取 1 条" in operation["description"]
assert (
"单轮、多轮、工具和图片各执行 1 条"
in schema["components"]["schemas"]["StartRunRequest"]["properties"]["profile"][
"description"
]
)
assert "completed_with_errors" in operation["description"]
assert "REQUEST_RETRY_COUNT" in operation["description"]
assert (
"completed_count + error_count"
in schema["paths"]["/api/v1/runs/{run_id}"]["get"]["description"]
)
assert "terminal" in schema["paths"]["/api/v1/runs/{run_id}"]["get"]["description"]
assert (
"needs_human_review"
in schema["paths"]["/api/v1/runs/{run_id}/results"]["get"]["description"]
)
assert "model_input" in schema["components"]["schemas"]["ResultItem"]["properties"]
result_properties = schema["components"]["schemas"]["ResultItem"]["properties"]
assert {"execution_status", "verdict"} <= set(result_properties)
assert "status" not in result_properties
assert "/runs/{run_id}/results" in operation["description"]
assert response["examples"][0]["run_id"] == 42
assert response["examples"][0]["status"] == "pending"
assert "202" in operation["responses"]
assert "Idempotency-Key" in operation["description"]
assert "409" in operation["responses"]
resume = schema["paths"]["/api/v1/runs/{run_id}/resume"]["post"]
assert "不会再次请求模型" in resume["description"]
assert "skipped_count" in schema["components"]["schemas"]["ResumeRunResponse"]["properties"]
def test_reports_openapi_declares_derived_read_only_resource():
schema = TestClient(app).get("/openapi.json").json()
assert set(schema["paths"]["/api/v1/reports"]) == {"get"}
assert set(schema["paths"]["/api/v1/reports/{run_id}"]) == {"get"}
assert "实时计算" in schema["paths"]["/api/v1/reports"]["get"]["description"]
assert "404" in schema["paths"]["/api/v1/reports/{run_id}"]["get"]["responses"]