feat(phase-32): add automated tests V3 for data sources, scoring, campaigns and snapshots (T-235 to T-237)
This commit is contained in:
@@ -1,16 +1,45 @@
|
||||
"""Pytest fixtures and configuration for backend tests."""
|
||||
"""Pytest fixtures and configuration for backend tests.
|
||||
|
||||
The conftest intentionally avoids importing ``app.main`` at module level
|
||||
because that triggers heavy side-effect imports (boto3, APScheduler, etc.)
|
||||
which are NOT needed for unit tests. The ``client`` fixture lazily imports
|
||||
the FastAPI app only when actually requested.
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
# Set DATABASE_URL to SQLite *before* any app module is imported so that
|
||||
# the lazy engine in app.database never tries to connect to PostgreSQL.
|
||||
os.environ.setdefault("DATABASE_URL", "sqlite:///:memory:")
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy import JSON, String, Text, create_engine, event
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
from sqlalchemy.pool import StaticPool
|
||||
|
||||
from app.main import app
|
||||
from app.database import Base, get_db
|
||||
from app.database import Base
|
||||
|
||||
# ── Patch PostgreSQL-specific column types so SQLite can handle them ─────
|
||||
# Must run BEFORE importing models, because column type objects are
|
||||
# instantiated at class-definition time.
|
||||
from sqlalchemy.dialects.postgresql import UUID as PG_UUID, JSONB as PG_JSONB
|
||||
|
||||
# Tell SQLAlchemy: when compiling for SQLite, render JSONB as plain JSON
|
||||
# and PostgreSQL UUID as CHAR(32).
|
||||
from sqlalchemy.dialects.sqlite.base import SQLiteTypeCompiler
|
||||
|
||||
if not hasattr(SQLiteTypeCompiler, "visit_JSONB"):
|
||||
SQLiteTypeCompiler.visit_JSONB = lambda self, type_, **kw: "JSON"
|
||||
|
||||
if not hasattr(SQLiteTypeCompiler, "visit_UUID"):
|
||||
SQLiteTypeCompiler.visit_UUID = lambda self, type_, **kw: "CHAR(32)"
|
||||
|
||||
from app.auth import hash_password
|
||||
from app.models.user import User
|
||||
|
||||
# ── Import all models so Base.metadata knows about every table ──────────
|
||||
import app.models # noqa: F401 — triggers model registration via __init__
|
||||
|
||||
# Use in-memory SQLite for tests
|
||||
SQLALCHEMY_DATABASE_URL = "sqlite:///:memory:"
|
||||
|
||||
@@ -19,6 +48,14 @@ engine = create_engine(
|
||||
connect_args={"check_same_thread": False},
|
||||
poolclass=StaticPool,
|
||||
)
|
||||
|
||||
# SQLite needs PRAGMA foreign_keys to enforce FK constraints
|
||||
@event.listens_for(engine, "connect")
|
||||
def _set_sqlite_pragma(dbapi_conn, connection_record):
|
||||
cursor = dbapi_conn.cursor()
|
||||
cursor.execute("PRAGMA foreign_keys=ON")
|
||||
cursor.close()
|
||||
|
||||
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||
|
||||
|
||||
@@ -43,13 +80,21 @@ def db():
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def client(db):
|
||||
"""Create a test client with database override."""
|
||||
"""Create a test client with database override.
|
||||
|
||||
Imports ``app.main`` lazily to avoid pulling in boto3 / APScheduler
|
||||
when only the ``db`` fixture is needed.
|
||||
"""
|
||||
from app.main import app
|
||||
from app.database import get_db
|
||||
|
||||
app.dependency_overrides[get_db] = override_get_db
|
||||
Base.metadata.create_all(bind=engine)
|
||||
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
with TestClient(app) as test_client:
|
||||
yield test_client
|
||||
|
||||
|
||||
Base.metadata.drop_all(bind=engine)
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user