"""Shared test fixtures for all test categories.""" import asyncio import os from typing import AsyncGenerator, Generator import pytest import pytest_asyncio from fastapi.testclient import TestClient from sqlalchemy import create_engine, text from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.orm import sessionmaker from src.config import Settings, build_database_url from src.models.base import Base from src.main import app # Unit test fixtures (SQLite in-memory) @pytest.fixture(scope="session") def sqlite_engine(): """Create a SQLite in-memory engine for unit tests.""" engine = create_engine("sqlite:///:memory:", connect_args={"check_same_thread": False}) Base.metadata.create_all(engine) yield engine engine.dispose() @pytest.fixture def sqlite_session(sqlite_engine) -> Generator: """Provide a SQLite session for unit tests.""" connection = sqlite_engine.connect() transaction = connection.begin() session = sessionmaker(bind=connection)() yield session session.close() transaction.rollback() connection.close() # Integration test fixtures (PostgreSQL) TEST_DATABASE_URL = build_database_url( user="headquarter", password="headquarter", host="localhost", port=5432, database="headquarter", ) @pytest_asyncio.fixture(scope="session") async def postgres_engine(): """Create a PostgreSQL engine for integration tests.""" engine = create_async_engine(TEST_DATABASE_URL) async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) yield engine await engine.dispose() @pytest_asyncio.fixture async def db_session(postgres_engine) -> AsyncGenerator[AsyncSession, None]: """Provide a database session with transaction rollback.""" async with postgres_engine.connect() as connection: transaction = await connection.begin_nested() session_factory = async_sessionmaker( connection, expire_on_commit=False, class_=AsyncSession ) session = session_factory() yield session await session.close() await transaction.rollback() @pytest.fixture def test_client() -> Generator[TestClient, None, None]: """Provide a FastAPI test client.""" with TestClient(app) as client: yield client @pytest.fixture(autouse=True) def configure_test_env(monkeypatch): """Configure environment for testing.""" monkeypatch.setenv("DATABASE_URL", TEST_DATABASE_URL) monkeypatch.setenv("APP_ENV", "testing")