test(api): фикстура db_session и снимок схемы OpenAPI тяжёлых GET
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1d885d1bbd
commit
0175759f95
@ -13,8 +13,15 @@ from src.main import app
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def client():
|
def db_session():
|
||||||
|
"""Сессия БД теста: её же использует client, всё откатывается в конце теста."""
|
||||||
db_ref = SessionLocal()
|
db_ref = SessionLocal()
|
||||||
|
yield db_ref
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def client(db_session):
|
||||||
|
db_ref = db_session
|
||||||
loop_ref = None
|
loop_ref = None
|
||||||
|
|
||||||
async def _get_db():
|
async def _get_db():
|
||||||
|
|||||||
66
api/tests/integration/test_heavy_get_json.py
Normal file
66
api/tests/integration/test_heavy_get_json.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
"""AURORA-1848: тяжёлые GET отдают готовый JSON из Postgres.
|
||||||
|
|
||||||
|
Эталон — старый путь (методы репозиториев и сервисов, которыми пользуется выгрузка Excel)
|
||||||
|
в той же сессии теста. Спека: openspec/changes/aurora-1848-sheet-json/specs/sheet-read-api/spec.md
|
||||||
|
"""
|
||||||
|
from types import SimpleNamespace
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from src.main import app
|
||||||
|
|
||||||
|
ADMIN = SimpleNamespace(id=1, role_id=1) # fixture.sql: admin
|
||||||
|
ISP = SimpleNamespace(id=2, role_id=2) # fixture.sql: isp1, EXECUTOR_DFIP
|
||||||
|
YEAR = 2026
|
||||||
|
|
||||||
|
HEAVY_GET_PATHS = [
|
||||||
|
"/api/v1/form/{form_id}/sheet/{sheet}",
|
||||||
|
"/api/v1/svod/1/{sheet}/{year}",
|
||||||
|
"/api/v1/svod/2/{sheet}/{year}",
|
||||||
|
"/api/v1/projects/{project_id}/report/{year}/{report_type}",
|
||||||
|
"/api/v1/rf-rollup/{branch_id}/{year}",
|
||||||
|
"/api/v1/projects/{project_id}/summary",
|
||||||
|
"/api/v1/projects/plan-summary",
|
||||||
|
"/api/v1/projects/fact-summary",
|
||||||
|
"/api/v1/projects/detail-summary",
|
||||||
|
]
|
||||||
|
OPENAPI_REF = "#/components/schemas/BaseListResponse_SheetResponse_"
|
||||||
|
|
||||||
|
|
||||||
|
def _payload(rows) -> list[dict]:
|
||||||
|
"""Строки старого пути в том виде, в каком их отдавал BaseListResponse[SheetResponse]."""
|
||||||
|
return [{"row_type": r[0], "depth": r[1], "sort_order": r[2], "data": r[3]} for r in rows]
|
||||||
|
|
||||||
|
|
||||||
|
def old_rows(client, coro_factory) -> list[dict]:
|
||||||
|
"""Вызвать старый метод (coro_factory() -> awaitable list[tuple]) в цикле приложения."""
|
||||||
|
async def _go():
|
||||||
|
return _payload(await coro_factory())
|
||||||
|
|
||||||
|
return client.portal.call(_go)
|
||||||
|
|
||||||
|
|
||||||
|
def expected_sheet(rows: list[dict]) -> list[dict]:
|
||||||
|
"""Ожидаемый ответ листа и сводов по эталону старого пути. Фаза B (Task 13) меняет тело на strip_nulls."""
|
||||||
|
return rows
|
||||||
|
|
||||||
|
|
||||||
|
def get_ok(client, url, headers, params=None) -> list[dict]:
|
||||||
|
r = client.get(url, headers=headers, params=params)
|
||||||
|
assert r.status_code == 200, r.text
|
||||||
|
assert r.headers["content-type"] == "application/json"
|
||||||
|
assert float(r.headers["x-db-time-ms"]) >= 0
|
||||||
|
body = r.json()
|
||||||
|
assert list(body) == ["success", "message", "result", "count"]
|
||||||
|
assert body["success"] is True and body["message"] is None
|
||||||
|
assert body["count"] == len(body["result"])
|
||||||
|
for row in body["result"]:
|
||||||
|
assert row.keys() == {"row_type", "depth", "sort_order", "data"}
|
||||||
|
return body["result"]
|
||||||
|
|
||||||
|
|
||||||
|
def test_openapi_heavy_get_schema_unchanged():
|
||||||
|
spec = app.openapi()
|
||||||
|
for path in HEAVY_GET_PATHS:
|
||||||
|
schema = spec["paths"][path]["get"]["responses"]["200"]["content"]["application/json"]["schema"]
|
||||||
|
assert schema == {"$ref": OPENAPI_REF}, path
|
||||||
Loading…
x
Reference in New Issue
Block a user