OC_P8 / tests /integration /test_api.py
KLEB38's picture
Upload folder using huggingface_hub
9331de5 verified
Raw
History Blame Contribute Delete
3.13 kB
"""Integration tests that boot the FastAPI app via TestClient.
The app is configured to use synthetic artefacts via env vars, so these
tests run in seconds and don't need the real 5 GB of training data.
"""
from __future__ import annotations
import importlib
import pytest
from fastapi.testclient import TestClient
@pytest.fixture
def client(patched_settings): # patched_settings sets the env vars first
"""Build a TestClient against a freshly-loaded app.
Re-import api.main so it picks up the patched api.settings module.
"""
import api.main as main_module
importlib.reload(main_module)
with TestClient(main_module.app) as test_client:
yield test_client
def test_health_endpoint(client):
resp = client.get("/health")
assert resp.status_code == 200
payload = resp.json()
assert payload["status"] == "ok"
assert payload["model_version"] == "test-1"
def test_swagger_docs_available(client):
"""The brief explicitly requires Swagger documentation."""
resp = client.get("/docs")
assert resp.status_code == 200
def test_openapi_schema(client):
resp = client.get("/openapi.json")
assert resp.status_code == 200
schema = resp.json()
assert "/predict" in schema["paths"]
def test_model_info_endpoint(client):
resp = client.get("/model/info")
assert resp.status_code == 200
payload = resp.json()
assert payload["threshold"] == 0.33
assert payload["version"] == "test-1"
assert payload["n_features_expected"] > 0
def test_predict_known_client(client, valid_payload):
resp = client.post("/predict", json=valid_payload)
assert resp.status_code == 200, resp.text
payload = resp.json()
assert payload["sk_id_curr"] == valid_payload["SK_ID_CURR"]
assert payload["client_known"] is True
assert payload["decision"] in {"GRANTED", "REFUSED"}
assert 0.0 <= payload["probability_default"] <= 1.0
assert payload["threshold"] == 0.33
assert payload["model_version"] == "test-1"
def test_predict_unknown_client(client, valid_payload):
valid_payload["SK_ID_CURR"] = 999_999_999 # absent from synthetic feature store
resp = client.post("/predict", json=valid_payload)
assert resp.status_code == 200, resp.text
assert resp.json()["client_known"] is False
def test_predict_rejects_negative_income(client, valid_payload):
valid_payload["AMT_INCOME_TOTAL"] = -1.0
resp = client.post("/predict", json=valid_payload)
assert resp.status_code == 422
def test_predict_rejects_missing_required_field(client, valid_payload):
del valid_payload["DAYS_BIRTH"]
resp = client.post("/predict", json=valid_payload)
assert resp.status_code == 422
def test_predict_rejects_extra_field(client, valid_payload):
valid_payload["__injection__"] = "evil"
resp = client.post("/predict", json=valid_payload)
assert resp.status_code == 422
def test_predict_rejects_unknown_contract_type(client, valid_payload):
valid_payload["NAME_CONTRACT_TYPE"] = "Bitcoin loans"
resp = client.post("/predict", json=valid_payload)
assert resp.status_code == 422