""" Pytest configuration and fixtures for testing Provides shared fixtures for database, client, and test data """ import pytest import asyncio from typing import AsyncGenerator, Generator from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker from fastapi.testclient import TestClient from app.main import app from app.database import Base, get_db from app.config import settings # Test database URL (use separate test database) TEST_DATABASE_URL = settings.DATABASE_URL.replace("/apac_ops_bot", "/apac_ops_bot_test") @pytest.fixture(scope="session") def event_loop() -> Generator: """ Create event loop for async tests """ loop = asyncio.get_event_loop_policy().new_event_loop() yield loop loop.close() @pytest.fixture(scope="session") async def test_engine(): """ Create test database engine """ engine = create_async_engine(TEST_DATABASE_URL, echo=True) # Create all tables async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) yield engine # Drop all tables after tests async with engine.begin() as conn: await conn.run_sync(Base.metadata.drop_all) await engine.dispose() @pytest.fixture async def db_session(test_engine) -> AsyncGenerator[AsyncSession, None]: """ Create database session for tests """ async_session = async_sessionmaker( test_engine, class_=AsyncSession, expire_on_commit=False, ) async with async_session() as session: yield session await session.rollback() @pytest.fixture def client(db_session: AsyncSession) -> TestClient: """ Create FastAPI test client with test database """ async def override_get_db(): yield db_session app.dependency_overrides[get_db] = override_get_db with TestClient(app) as test_client: yield test_client app.dependency_overrides.clear()