perf: reuse the test schema instead of rebuilding it per test
The autouse _setup_db fixture ran create_all + drop_all for every test in the suite, including the many that never open a session. That cycle costs ~49ms against these 22 tables; truncating them instead costs ~6ms for the same guarantee of an empty database per test. Build the schema once, then delete every row before each subsequent test. No model sets sqlite_autoincrement, so SQLite reuses rowids after a full delete and generated ids still restart at 1. Measured over 874 tests, deterministic order: 138.6s -> 74.5s (~46%). Verified green under pytest-randomly's default random ordering as well. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+20
-3
@@ -15,6 +15,8 @@ from sqlalchemy.ext.asyncio import (
|
||||
create_async_engine,
|
||||
)
|
||||
|
||||
from sqlalchemy import delete
|
||||
|
||||
from app.database import Base
|
||||
from app.providers.protocol import OHLCVData
|
||||
|
||||
@@ -32,14 +34,29 @@ _test_session_factory = async_sessionmaker(
|
||||
)
|
||||
|
||||
|
||||
_schema_created = False
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
async def _setup_db():
|
||||
"""Create all tables before each test and drop them after."""
|
||||
"""Hand every test an empty database.
|
||||
|
||||
The schema is built once and then truncated per test rather than dropped and
|
||||
recreated. A create_all/drop_all cycle costs ~49ms against these 22 tables and
|
||||
ran for every test in the suite — including the many that never open a session
|
||||
— where deleting every row costs ~6ms for the same guarantee. No model sets
|
||||
``sqlite_autoincrement``, so SQLite reuses rowids after a full delete and
|
||||
generated ids still restart at 1.
|
||||
"""
|
||||
global _schema_created
|
||||
async with _test_engine.begin() as conn:
|
||||
if not _schema_created:
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
_schema_created = True
|
||||
else:
|
||||
for table in reversed(Base.metadata.sorted_tables):
|
||||
await conn.execute(delete(table))
|
||||
yield
|
||||
async with _test_engine.begin() as conn:
|
||||
await conn.run_sync(Base.metadata.drop_all)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
Reference in New Issue
Block a user