dataloader/tests/conftest.py

105 lines
3.0 KiB
Python
Raw Normal View History

2025-11-05 11:31:19 +01:00
# tests/conftest.py
2025-11-05 12:41:56 +01:00
from __future__ import annotations
2025-11-05 11:31:19 +01:00
import asyncio
import sys
from typing import AsyncGenerator
2025-11-05 12:41:56 +01:00
from uuid import uuid4
2025-11-05 11:31:19 +01:00
import pytest
2025-11-05 12:41:56 +01:00
import pytest_asyncio
2025-11-05 11:31:19 +01:00
from dotenv import load_dotenv
from httpx import AsyncClient, ASGITransport
from sqlalchemy import text
2025-11-05 12:41:56 +01:00
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession, async_sessionmaker
2025-11-05 11:31:19 +01:00
load_dotenv()
from dataloader.api import app_main
from dataloader.config import APP_CONFIG
2025-11-05 12:41:56 +01:00
from dataloader.context import APP_CTX, get_session
from dataloader.storage.models import Base
from dataloader.storage.engine import create_engine, create_sessionmaker
2025-11-05 11:31:19 +01:00
if sys.platform == "win32":
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
2025-11-05 12:41:56 +01:00
@pytest_asyncio.fixture(scope="function")
2025-11-05 11:31:19 +01:00
async def db_engine() -> AsyncGenerator[AsyncEngine, None]:
"""
2025-11-05 12:41:56 +01:00
Создаёт тестовый движок для теста.
Использует реальную БД из конфига.
2025-11-05 11:31:19 +01:00
"""
2025-11-05 12:41:56 +01:00
engine = create_engine(APP_CONFIG.pg.url)
2025-11-05 11:31:19 +01:00
yield engine
await engine.dispose()
2025-11-05 12:41:56 +01:00
@pytest_asyncio.fixture(scope="function")
async def db_session(db_engine: AsyncEngine) -> AsyncGenerator[AsyncSession, None]:
2025-11-05 11:31:19 +01:00
"""
2025-11-05 12:41:56 +01:00
Предоставляет сессию БД для каждого теста.
НЕ использует транзакцию, чтобы работали advisory locks.
2025-11-05 11:31:19 +01:00
"""
2025-11-05 12:41:56 +01:00
sessionmaker = async_sessionmaker(bind=db_engine, expire_on_commit=False, class_=AsyncSession)
async with sessionmaker() as session:
yield session
await session.rollback()
2025-11-05 11:31:19 +01:00
2025-11-05 12:41:56 +01:00
@pytest_asyncio.fixture(scope="function")
async def clean_queue_tables(db_session: AsyncSession) -> None:
2025-11-05 11:31:19 +01:00
"""
2025-11-05 12:41:56 +01:00
Очищает таблицы очереди перед каждым тестом.
2025-11-05 11:31:19 +01:00
"""
2025-11-05 12:41:56 +01:00
schema = APP_CONFIG.pg.schema_queue
await db_session.execute(text(f"TRUNCATE TABLE {schema}.dl_job_events CASCADE"))
await db_session.execute(text(f"TRUNCATE TABLE {schema}.dl_jobs CASCADE"))
await db_session.commit()
2025-11-05 11:31:19 +01:00
2025-11-05 12:41:56 +01:00
@pytest_asyncio.fixture
2025-11-05 11:31:19 +01:00
async def client(db_session: AsyncSession) -> AsyncGenerator[AsyncClient, None]:
"""
2025-11-05 12:41:56 +01:00
HTTP клиент для тестирования API.
2025-11-05 11:31:19 +01:00
"""
async def override_get_session() -> AsyncGenerator[AsyncSession, None]:
yield db_session
app_main.dependency_overrides[get_session] = override_get_session
transport = ASGITransport(app=app_main)
async with AsyncClient(transport=transport, base_url="http://test") as c:
yield c
app_main.dependency_overrides.clear()
2025-11-05 12:41:56 +01:00
@pytest.fixture
def job_id() -> str:
"""
Генерирует уникальный job_id для тестов.
"""
return str(uuid4())
@pytest.fixture
def queue_name() -> str:
"""
Возвращает имя тестовой очереди.
"""
return "test.queue"
@pytest.fixture
def task_name() -> str:
"""
Возвращает имя тестовой задачи.
"""
return "test.task"