"""Pytest config — no DB / no network. Tests target pure functions only. Heavy runtime deps (fastapi, httpx, sqlalchemy, pydantic-settings, tenacity) are installed inside the container but not necessarily on the host. Tests that need them use pytest.importorskip; the full suite runs via `docker compose run --rm app pytest tests/`.""" from __future__ import annotations import os import sys from pathlib import Path ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(ROOT)) # Sentinel env so importing app.config doesn't try to read a missing .env. os.environ.setdefault("DATABASE_URL", "sqlite+aiosqlite:///:memory:") os.environ.setdefault("CASSANDRA_MOCK", "1") import pytest @pytest.fixture async def db_factory(tmp_path): """Per-test sqlite engine + async session factory. Creates a fresh sqlite database file under ``tmp_path``, applies ``Base.metadata.create_all``, and rebinds ``app.db._engine`` / ``app.db._session_factory`` so module-level helpers (which look these up at call time) see the test engine. Yields the ``async_sessionmaker``. Tests use it like: async def test_foo(db_factory): async with db_factory() as session: ... """ from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine from app import db as db_mod from app.db import Base import app.models # noqa: F401 — registers models on Base.metadata engine = create_async_engine(f"sqlite+aiosqlite:///{tmp_path}/test.db") factory = async_sessionmaker(engine, expire_on_commit=False) db_mod._engine = engine db_mod._session_factory = factory async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) yield factory await engine.dispose()