diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2483878..8b3d0e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -69,6 +69,22 @@ jobs: print("infra-ready") PY + - name: Prepare test database schema + run: | + python - <<'PY' + import asyncio + from src.models.database import Base + from src.models.db import engine + + async def main() -> None: + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + await engine.dispose() + + asyncio.run(main()) + print("schema-ready") + PY + - name: Run tests run: pytest -q -m "not integration" @@ -136,6 +152,22 @@ jobs: print("infra-ready") PY + - name: Prepare test database schema + run: | + python - <<'PY' + import asyncio + from src.models.database import Base + from src.models.db import engine + + async def main() -> None: + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + await engine.dispose() + + asyncio.run(main()) + print("schema-ready") + PY + - name: Run compare blackbox integration test run: pytest -q -m integration tests/integration/test_compare_blackbox.py diff --git a/pyproject.toml b/pyproject.toml index ccb5df3..3c687b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,6 +73,7 @@ select = ["E", "F", "I", "N", "W", "UP"] testpaths = ["tests"] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "session" +asyncio_default_test_loop_scope = "session" markers = [ "integration: tests that require real infra/services", ] diff --git a/tests/conftest.py b/tests/conftest.py index a31aef0..ffb6a66 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,6 +6,8 @@ from httpx import ASGITransport, AsyncClient from src.api.main import app +from src.models.database import Base +from src.models.db import engine @pytest.fixture(scope="session") @@ -19,9 +21,18 @@ def event_loop(): loop.close() +@pytest.fixture(scope="session", autouse=True) +async def ensure_db_schema(): + """Ensure required tables exist even when app lifespan is not triggered.""" + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.create_all) + yield + + @pytest.fixture async def client(): """Async test client for the FastAPI app.""" - transport = ASGITransport(app=app) - async with AsyncClient(transport=transport, base_url="http://test") as ac: - yield ac + async with app.router.lifespan_context(app): + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as ac: + yield ac