tests: extract _build_session_factory to a shared conftest fixture

The same per-test sqlite-engine setup was duplicated across 14 test
files (~30 lines each). Consolidated into a single async fixture
`db_factory` in tests/conftest.py; tests now take db_factory as a
parameter and use `async with db_factory() as session` directly.

No behaviour change — same function-scope, same in-memory schema
created via Base.metadata.create_all, same app.db._engine /
_session_factory rebinding so module-level helpers see the test
engine. Just ~420 lines of boilerplate removed.
This commit is contained in:
Giorgio Gilestro 2026-05-27 20:50:09 +02:00
parent b13caa4c51
commit dcc2c07111
5 changed files with 167 additions and 250 deletions

View file

@ -9,34 +9,13 @@ from unittest.mock import AsyncMock
import pytest
def _build_session_factory(tmp_path):
"""Spin up a fresh in-memory schema and return (engine, factory, setup).
Mirrors tests/test_llm_csv_parser.py / tests/test_referral_conversion.py."""
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
from app import db as db_mod
from app.db import Base
import app.models # noqa: F401
engine = create_async_engine(f"sqlite+aiosqlite:///{tmp_path}/tv.db")
factory = async_sessionmaker(engine, expire_on_commit=False)
db_mod._engine = engine
db_mod._session_factory = factory
async def _setup():
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
return engine, factory, _setup
async def test_validate_happy_path(tmp_path, monkeypatch):
async def test_validate_happy_path(db_factory, monkeypatch):
from app.routers.ticker_validate import validate_ticker
from app.services.market import Quote
import app.routers.ticker_validate as mod
_, factory, setup = _build_session_factory(tmp_path)
await setup()
factory = db_factory
# Mock fetch_yahoo to return a successful quote.
async def _fake_yahoo(client, symbol, label, note, anchor=None):
@ -61,13 +40,12 @@ async def test_validate_happy_path(tmp_path, monkeypatch):
assert result["as_of"] == "2026-05-27"
async def test_validate_unknown_symbol(tmp_path, monkeypatch):
async def test_validate_unknown_symbol(db_factory, monkeypatch):
from app.routers.ticker_validate import validate_ticker
from app.services.market import Quote
import app.routers.ticker_validate as mod
_, factory, setup = _build_session_factory(tmp_path)
await setup()
factory = db_factory
# Mock fetch_yahoo to return a Quote with error and no price.
async def _fake_yahoo(client, symbol, label, note, anchor=None):
@ -92,7 +70,7 @@ async def test_validate_empty_symbol_rejects():
assert "required" in result["error"].lower()
async def test_validate_seeds_universe_and_quote(tmp_path, monkeypatch):
async def test_validate_seeds_universe_and_quote(db_factory, monkeypatch):
"""Side-effect check: on success, the symbol is upserted into the
universe and a Quote row is written."""
from sqlalchemy import select
@ -102,8 +80,7 @@ async def test_validate_seeds_universe_and_quote(tmp_path, monkeypatch):
from app.services.market import Quote
import app.routers.ticker_validate as mod
_, factory, setup = _build_session_factory(tmp_path)
await setup()
factory = db_factory
upsert_calls: list[list[str]] = []