"""Shared pytest fixtures. Uses SQLite for speed (see ARCHITECTURE.md §4.8). Tests exercise the framework against an in-memory Postgres-shaped SQLAlchemy Base — no Alembic migrations in the test path; models create their tables from metadata. """ from __future__ import annotations import os from collections.abc import Iterator import pytest from fastapi.testclient import TestClient from sqlalchemy import create_engine from sqlalchemy.orm import Session, sessionmaker @pytest.fixture(scope="session", autouse=True) def _test_env() -> Iterator[None]: """Set minimum env vars required for `Settings()` to construct in tests.""" os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:") os.environ.setdefault("JWT_SECRET", "test-secret") os.environ.setdefault( "COLUMN_ENCRYPTION_KEY", "test-col-enc-key-32bytes-______________" ) os.environ.setdefault("ENV", "test") yield @pytest.fixture def db() -> Iterator[Session]: """Fresh in-memory SQLite DB per test with all model tables created. Import happens inside the fixture so the model modules register themselves on Base.metadata before create_all runs. """ import ypms.audit.models # noqa: F401 import ypms.framework.version_history # noqa: F401 import ypms.security.models # noqa: F401 import ypms.users.models # noqa: F401 from ypms.db import Base engine = create_engine("sqlite:///:memory:", future=True) Base.metadata.create_all(engine) SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True) session = SessionLocal() try: yield session finally: session.close() engine.dispose() @pytest.fixture def client() -> Iterator[TestClient]: from ypms.main import create_app app = create_app() with TestClient(app) as c: yield c