fix(tests): изолировать тесты от instance_settings в общей dev-БД
Тесты читали ту же instance_settings, что и dev-стенд: выключение chat/hand_queue в админке роняло пачку тестов, не связанных с самим переключением (наступила сессия 0.0.28). Фикстура clean_instance_settings (явная, не autouse — DELETE в savepoint держит блокировку строки до конца внешней транзакции теста, автовключение на тестах с отдельными подключениями к БД дало саморазблокировку) удаляет управляемые ключи перед тестом, чтение конфигурации падает на дефолты pydantic-моделей. Подключена в test_chat_ws.py и test_hand_queue_ws.py. MANAGED_KEYS в services/instance_settings.py — единый список управляемых ключей вместо локальной копии в тестовом файле.
This commit is contained in:
@@ -21,10 +21,11 @@ from sqlalchemy.dialects.postgresql import insert as pg_insert
|
||||
from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession
|
||||
from starlette.types import Message, Scope
|
||||
|
||||
from core.db import engine, get_session
|
||||
from core.db import engine, get_metrics_session, get_session
|
||||
from core.redis import redis_client
|
||||
from main import create_app
|
||||
from models.instance_setting import InstanceSetting
|
||||
from services.instance_settings import MANAGED_KEYS
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(autouse=True)
|
||||
@@ -88,6 +89,37 @@ async def _load_committed_instance_settings() -> dict[str, Any]:
|
||||
return {key: value for key, value in result.all()}
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def clean_instance_settings(db_session: AsyncSession) -> AsyncGenerator[None, None]:
|
||||
"""Изолировать тест от текущего состояния управляемых ключей `instance_settings` в
|
||||
общей dev-БД (тоггл чата, поднятия руки и т.п. — живые настройки разработчика, а не
|
||||
тестовые данные).
|
||||
|
||||
Удаляет строки `MANAGED_KEYS` внутри savepoint-транзакции теста (`db_session`) —
|
||||
последующее чтение конфигурации (`InstanceSettingsService.get`/`load_effective_config`)
|
||||
падает на дефолты pydantic-моделей (например, `ChatConfig.enabled == True`), одинаковые
|
||||
независимо от того, что реально сохранено в dev-БД в момент прогона. Savepoint
|
||||
откатывается в `db_connection` по завершении теста — восстанавливать исходные строки
|
||||
вручную не нужно, в отличие от `_preserve_instance_settings` (та фикстура страхует от
|
||||
записи МИМО savepoint, эта — от чтения ИЗ него состояния, унаследованного от dev-БД).
|
||||
|
||||
НЕ autouse и намеренно: `DELETE` внутри savepoint держит Postgres-блокировку на
|
||||
строке до конца ВНЕШНЕЙ транзакции теста (`db_connection`, откатывается только в
|
||||
teardown) — savepoint её не освобождает раньше срока. Тесты, которые параллельно
|
||||
внутри СЕБЯ же пишут в те же ключи через ОТДЕЛЬНОЕ реальное подключение
|
||||
(`async_session_maker`/`engine.connect()` — см. `test_transcription_disabled_setting_
|
||||
stops_run_pipeline`, `clean_bootstrap_managed_keys`), заблокировались бы сами на себе,
|
||||
если бы эта фикстура применялась к ним автоматически (наступили при первой попытке
|
||||
сделать её autouse — само-дедлок, тест висел до ручного убийства процесса). Поэтому
|
||||
запрашивать явно, только в тестах, где именно ОНА обеспечивает изоляцию (WS чата/
|
||||
очереди рук и т.п.), а не там, где тест сам управляет состоянием через реальные
|
||||
коммиты.
|
||||
"""
|
||||
await db_session.execute(delete(InstanceSetting).where(InstanceSetting.key.in_(MANAGED_KEYS)))
|
||||
await db_session.commit()
|
||||
yield
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def db_connection() -> AsyncGenerator[AsyncConnection, None]:
|
||||
async with engine.connect() as connection:
|
||||
|
||||
Reference in New Issue
Block a user