yusufcalisir's picture
deploy: Hugging Face space upload
eff6797
Raw History Blame Contribute Delete
4.83 kB
"""OpenAPI Specification and Schema Invariants Contract Test Suite.
Validates the full OpenAPI 3.x schema generated by FastAPI, ensuring:
1. Complete path registration across all routers.
2. Valid operation IDs, methods, and tags.
3. Response schemas and JSON content-type definitions.
4. Schema integrity in components (no broken $ref pointers).
"""
from __future__ import annotations
import pytest
from app.main import app
@pytest.fixture(scope="module")
def openapi_schema() -> dict:
"""Generate OpenAPI specification dictionary from FastAPI app."""
schema = app.openapi()
assert isinstance(schema, dict), "OpenAPI schema must be a dictionary"
return schema
def test_openapi_core_structure(openapi_schema: dict):
"""Validate core OpenAPI document properties."""
assert "openapi" in openapi_schema
assert openapi_schema["openapi"].startswith("3.")
assert "info" in openapi_schema
assert "title" in openapi_schema["info"]
assert "version" in openapi_schema["info"]
assert "paths" in openapi_schema
assert len(openapi_schema["paths"]) >= 25, "At least 25 core API paths must be registered"
def test_openapi_required_routes_presence(openapi_schema: dict):
"""Verify that all essential platform routes are present in OpenAPI schema."""
paths = openapi_schema["paths"]
expected_critical_endpoints = [
"/api/v1/simulations",
"/api/v1/simulations/{simulation_id}",
"/api/v1/simulations/{simulation_id}/ai-act-report",
"/api/v1/banks",
"/api/v1/banks/distributions",
"/api/v1/training/{simulation_id}/rounds",
"/api/v1/alerts",
"/api/v1/alerts/{alert_id}",
"/api/v1/alerts/{alert_id}/explain",
"/api/v1/alerts/{alert_id}/counterfactuals",
"/api/v1/alerts/{alert_id}/decision-replay",
"/api/v1/alerts/{alert_id}/gnn-explanation",
"/api/v1/cases",
"/api/v1/cases/{case_id}",
"/api/v1/cases/{case_id}/evidence",
"/api/v1/cases/audit/logs",
"/api/v1/entities",
"/api/v1/graph/{entity_id}",
"/api/v1/graph/stats/summary",
"/api/v1/entities/psi",
"/api/v1/entities/fuzzy-resolve",
"/api/v1/rules",
"/api/v1/rules/test",
"/api/v1/security/status",
"/api/v1/security/abac/evaluate",
"/api/v1/security/audit-chain",
"/api/v1/security/audit-chain/verify",
"/api/v1/monitoring/drift/analyze",
"/api/v1/monitoring/calibration",
"/api/v1/monitoring/alerts",
"/api/v1/coordinator/clients",
"/api/v1/coordinator/negotiate",
"/api/v1/privacy-defense/aggregation-methods",
"/api/v1/privacy-defense/budget-log",
"/api/v1/privacy-defense/audit/mia",
"/api/v1/privacy-defense/audit/model-inversion",
"/api/v1/registry/{simulation_id}/versions",
"/api/v1/registry/{simulation_id}/shadow/metrics",
"/api/v1/scenarios",
"/health",
]
for endpoint in expected_critical_endpoints:
assert endpoint in paths, f"Missing critical endpoint in OpenAPI spec: {endpoint}"
def test_openapi_operation_contracts(openapi_schema: dict):
"""Validate HTTP methods, status codes, and response structures for all operations."""
paths = openapi_schema["paths"]
for path_str, methods in paths.items():
for method_name, operation in methods.items():
if method_name.startswith("x-") or method_name == "parameters":
continue
assert isinstance(operation, dict), f"Operation {method_name} {path_str} must be a dict"
assert "responses" in operation, f"Operation {method_name} {path_str} must declare responses"
# Verify status code contracts
responses = operation["responses"]
has_success_code = any(
code.startswith("2") or code == "default" for code in responses
)
assert has_success_code, f"Operation {method_name} {path_str} missing 2xx success response"
def test_openapi_component_schema_integrity(openapi_schema: dict):
"""Verify that all schemas in components have valid property definitions and resolvable refs."""
components = openapi_schema.get("components", {})
schemas = components.get("schemas", {})
assert len(schemas) > 0, "OpenAPI components must contain model schemas"
for schema_name, schema_obj in schemas.items():
assert isinstance(schema_obj, dict), f"Schema {schema_name} must be a dictionary"
# Verify that schema defines title or type
assert "type" in schema_obj or "properties" in schema_obj or "enum" in schema_obj or "allOf" in schema_obj or "anyOf" in schema_obj, (
f"Schema {schema_name} must have a valid structural descriptor"
)