test: проверка остановки воркера по снятым задачам и устойчивый teardown uploads (T10.1, T10.2)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Andrey Epifancev 2026-10-04 03:29:28 +04:00
parent 5c96189146
commit 6491fdd538

View File

@ -15,6 +15,7 @@ Spec tabular-recognition-service: «Ack раньше результата», «
""" """
import asyncio import asyncio
import contextlib
import copy import copy
import importlib import importlib
import io import io
@ -166,9 +167,13 @@ async def uploads() -> AsyncIterator[Uploads]:
try: try:
yield store yield store
finally: finally:
for bucket, key in store.keys: try:
await client.remove_object(bucket, key) for bucket, key in store.keys:
await client.close_session() # сбой удаления одного объекта не должен оставлять в MinIO остальные
with contextlib.suppress(Exception):
await client.remove_object(bucket, key)
finally:
await client.close_session()
@pytest.fixture @pytest.fixture
@ -176,13 +181,17 @@ async def service(monkeypatch: pytest.MonkeyPatch) -> AsyncIterator[None]:
"""Приложение в процессе теста: lifespan с `NATS_ENABLED=True` (в `.env.test` — false); выход — остановка.""" """Приложение в процессе теста: lifespan с `NATS_ENABLED=True` (в `.env.test` — false); выход — остановка."""
monkeypatch.setattr(app_module.settings, "NATS_ENABLED", True) monkeypatch.setattr(app_module.settings, "NATS_ENABLED", True)
application = app_module.app application = app_module.app
tasks: list[asyncio.Task[None]] = []
async with application.router.lifespan_context(application): async with application.router.lifespan_context(application):
if not await application.state.nats.wait_ready(READY_TIMEOUT): if not await application.state.nats.wait_ready(READY_TIMEOUT):
pytest.fail( pytest.fail(
f"NATS недоступен ({app_module.settings.OPENBAO.NATS.NATS_URL}, .env.test; make up)", pytrace=False f"NATS недоступен ({app_module.settings.OPENBAO.NATS.NATS_URL}, .env.test; make up)", pytrace=False
) )
tasks = list(application.state.worker._tasks)
yield yield
assert application.state.worker._tasks == [], "рабочие корутины воркера не остановлены" # `_tasks` обнуляется в `stop()` безусловно — проверяем сами задачи, снятые до выхода из lifespan
assert tasks, "воркер не запустил рабочие корутины"
assert all(t.done() for t in tasks), "рабочие корутины воркера не остановлены"
@pytest.fixture @pytest.fixture