Skip to content

Commit 70a7880

Browse files
fix(e2e): resolve async fixture and API availability issues
- Use @pytest_asyncio.fixture for proper async fixture handling - Change pg_engine scope to function to avoid event loop conflicts - Load .env via dotenv for local DATABASE_URL discovery - Remove custom event_loop fixture (pytest-asyncio handles it) - Patch is_db_configured() to fix 503 Service Unavailable responses All 484 tests pass (465 unit/integration + 19 E2E). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent b3645ca commit 70a7880

2 files changed

Lines changed: 19 additions & 16 deletions

File tree

tests/e2e/conftest.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import os
99

1010
import pytest
11+
import pytest_asyncio
1112
from sqlalchemy import text
1213
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
1314

@@ -21,26 +22,22 @@
2122
TEST_THUMB_URL = "https://storage.googleapis.com/pyplots-images/test/thumb.png"
2223

2324

24-
@pytest.fixture(scope="session")
25-
def event_loop():
26-
"""Create event loop for session-scoped async fixtures."""
27-
import asyncio
25+
def _get_database_url():
26+
"""Get DATABASE_URL from environment, loading .env if needed."""
27+
from dotenv import load_dotenv
28+
load_dotenv()
29+
return os.environ.get("DATABASE_URL")
2830

29-
policy = asyncio.get_event_loop_policy()
30-
loop = policy.new_event_loop()
31-
yield loop
32-
loop.close()
3331

34-
35-
@pytest.fixture(scope="session")
32+
@pytest_asyncio.fixture(scope="function")
3633
async def pg_engine():
3734
"""
3835
Create PostgreSQL engine and setup test schema.
3936
4037
Creates a separate 'test_e2e' schema to isolate tests from production data.
41-
The schema is dropped and recreated at the start of the test session.
38+
The schema is dropped and recreated for each test.
4239
"""
43-
database_url = os.environ.get("DATABASE_URL")
40+
database_url = _get_database_url()
4441
if not database_url:
4542
pytest.skip("DATABASE_URL not set - skipping PostgreSQL E2E tests")
4643

@@ -61,7 +58,7 @@ async def pg_engine():
6158
await engine.dispose()
6259

6360

64-
@pytest.fixture
61+
@pytest_asyncio.fixture
6562
async def pg_session(pg_engine):
6663
"""Create session with test schema."""
6764
async_session = async_sessionmaker(pg_engine, class_=AsyncSession, expire_on_commit=False)
@@ -72,7 +69,7 @@ async def pg_session(pg_engine):
7269
await session.rollback()
7370

7471

75-
@pytest.fixture
72+
@pytest_asyncio.fixture
7673
async def pg_db_with_data(pg_session):
7774
"""
7875
Seed test schema with sample data.

tests/e2e/test_api_postgres.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
local development without PostgreSQL.
1010
"""
1111

12+
from unittest.mock import patch
13+
1214
import pytest
1315
from httpx import ASGITransport, AsyncClient
1416

@@ -35,8 +37,12 @@ async def override_get_db():
3537
yield pg_db_with_data
3638

3739
app.dependency_overrides[get_db] = override_get_db
38-
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as ac:
39-
yield ac
40+
41+
# Patch is_db_configured to return True (it checks env vars, not dependencies)
42+
with patch("api.dependencies.is_db_configured", return_value=True):
43+
async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as ac:
44+
yield ac
45+
4046
app.dependency_overrides.clear()
4147

4248

0 commit comments

Comments
 (0)