"""Shared pytest fixtures for the trading-bot test suite. Provides: - `db_session`: an `AsyncSession` against the dev Postgres (transaction-scoped, rolled back between tests). """ from __future__ import annotations import os from collections.abc import AsyncIterator import pytest_asyncio from sqlalchemy.ext.asyncio import ( AsyncSession, async_sessionmaker, create_async_engine, ) def _dev_db_url() -> str: return os.environ.get( "TRADING_TEST_DATABASE_URL", "postgresql+asyncpg://trading:trading@localhost:5432/trading_dev", ) @pytest_asyncio.fixture async def db_session() -> AsyncIterator[AsyncSession]: """Per-test session wrapped in a transaction that is rolled back at teardown.""" engine = create_async_engine(_dev_db_url(), echo=False) try: connection = await engine.connect() transaction = await connection.begin() session_factory = async_sessionmaker( bind=connection, class_=AsyncSession, expire_on_commit=False, join_transaction_mode="create_savepoint", ) session = session_factory() try: yield session finally: await session.close() await transaction.rollback() await connection.close() finally: await engine.dispose()