Skip to content

Commit 2df734c

Browse files
fix(tests): improve database cleanup and seeding in test fixtures
- Drop tables in foreign key order during setup and teardown - Use atomic commits for seeding test data to ensure integrity
1 parent 6cca872 commit 2df734c

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

tests/e2e/conftest.py

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import pytest
2020
import pytest_asyncio
21+
from sqlalchemy import text
2122
from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
2223

2324
from core.database.models import Base
@@ -74,8 +75,10 @@ async def pg_engine():
7475
try:
7576
async with asyncio.timeout(CONNECTION_TIMEOUT + 2):
7677
async with engine.begin() as conn:
77-
# Drop all tables for clean state
78-
await conn.run_sync(Base.metadata.drop_all)
78+
# Drop all tables in FK order (children before parents)
79+
await conn.execute(text("DROP TABLE IF EXISTS impls CASCADE"))
80+
await conn.execute(text("DROP TABLE IF EXISTS specs CASCADE"))
81+
await conn.execute(text("DROP TABLE IF EXISTS libraries CASCADE"))
7982
# Create fresh tables
8083
await conn.run_sync(Base.metadata.create_all)
8184
except (TimeoutError, asyncio.TimeoutError, OSError) as e:
@@ -87,13 +90,15 @@ async def pg_engine():
8790

8891
yield engine
8992

90-
# Cleanup: Drop all tables
93+
# Cleanup: Drop all tables in FK order (children before parents)
9194
async with engine.begin() as conn:
92-
await conn.run_sync(Base.metadata.drop_all)
95+
await conn.execute(text("DROP TABLE IF EXISTS impls CASCADE"))
96+
await conn.execute(text("DROP TABLE IF EXISTS specs CASCADE"))
97+
await conn.execute(text("DROP TABLE IF EXISTS libraries CASCADE"))
9398
await engine.dispose()
9499

95100

96-
@pytest_asyncio.fixture
101+
@pytest_asyncio.fixture(scope="function")
97102
async def pg_session(pg_engine):
98103
"""Create session for test database."""
99104
async_session = async_sessionmaker(pg_engine, class_=AsyncSession, expire_on_commit=False)
@@ -102,13 +107,16 @@ async def pg_session(pg_engine):
102107
await session.rollback()
103108

104109

105-
@pytest_asyncio.fixture
110+
@pytest_asyncio.fixture(scope="function")
106111
async def pg_db_with_data(pg_session):
107112
"""
108113
Seed test database with sample data.
109114
110115
Creates the same test data as tests/conftest.py:test_db_with_data
111116
but in the PostgreSQL test database.
117+
118+
Uses atomic commit: libraries + specs flushed first (FK targets),
119+
then impls added and everything committed together.
112120
"""
113121
from core.database.models import Impl, Library, Spec
114122

@@ -127,7 +135,6 @@ async def pg_db_with_data(pg_session):
127135
documentation_url="https://seaborn.pydata.org",
128136
description="Statistical data visualization",
129137
)
130-
pg_session.add_all([matplotlib_lib, seaborn_lib])
131138

132139
# Create specs
133140
scatter_spec = Spec(
@@ -152,8 +159,6 @@ async def pg_db_with_data(pg_session):
152159
issue=43,
153160
suggested="contributor2",
154161
)
155-
pg_session.add_all([scatter_spec, bar_spec])
156-
await pg_session.commit()
157162

158163
# Create implementations
159164
scatter_matplotlib = Impl(
@@ -188,8 +193,15 @@ async def pg_db_with_data(pg_session):
188193
python_version="3.13",
189194
library_version="3.10.0",
190195
)
196+
197+
# Add FK targets first (libraries and specs)
198+
pg_session.add_all([matplotlib_lib, seaborn_lib])
199+
pg_session.add_all([scatter_spec, bar_spec])
200+
await pg_session.flush() # Ensure FK targets exist before adding children
201+
202+
# Add FK children (implementations)
191203
pg_session.add_all([scatter_matplotlib, scatter_seaborn, bar_matplotlib])
192-
await pg_session.commit()
204+
await pg_session.commit() # Single atomic commit
193205

194206
# Expire all cached objects to ensure fresh loading with relationships
195207
pg_session.expire_all()

0 commit comments

Comments
 (0)