| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- """SQLAlchemy repository tests against an in-memory SQLite database.
- Verifies day routing (latest dt + specific dt + missing) and rolling-row column
- mapping against a real engine, with no Postgres needed.
- """
- from __future__ import annotations
- import pytest
- from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
- from app.db.models import (
- AdsTrdGroupFunnelDaily,
- AdsTrdGroupFunnelRolling,
- Base,
- )
- from app.schemas import DataStatus, Period
- from app.services.funnel import run_funnel_query
- from app.services.repository import SqlAlchemyFunnelRepository
- def _daily_row(dt: str, top: int) -> AdsTrdGroupFunnelDaily:
- return AdsTrdGroupFunnelDaily(
- dt=dt,
- uv_start=top,
- uv_show=int(top * 0.8),
- uv_detail=int(top * 0.5),
- uv_order=int(top * 0.2),
- uv_paid=int(top * 0.16),
- )
- def _rolling_row(dt: str, top7: int, top30: int) -> AdsTrdGroupFunnelRolling:
- return AdsTrdGroupFunnelRolling(
- dt=dt,
- uv_start_7d=top7,
- uv_show_7d=int(top7 * 0.8),
- uv_detail_7d=int(top7 * 0.5),
- uv_order_7d=int(top7 * 0.2),
- uv_paid_7d=int(top7 * 0.16),
- uv_start_30d=top30,
- uv_show_30d=int(top30 * 0.8),
- uv_detail_30d=int(top30 * 0.5),
- uv_order_30d=int(top30 * 0.2),
- uv_paid_30d=int(top30 * 0.16),
- )
- @pytest.fixture
- async def sqlite_sessionmaker():
- engine = create_async_engine("sqlite+aiosqlite:///:memory:")
- async with engine.begin() as conn:
- await conn.run_sync(Base.metadata.create_all)
- maker = async_sessionmaker(engine, expire_on_commit=False)
- yield maker
- await engine.dispose()
- async def test_empty_daily_returns_none(sqlite_sessionmaker) -> None:
- async with sqlite_sessionmaker() as session:
- repo = SqlAlchemyFunnelRepository(session)
- assert await repo.fetch_daily(None) is None
- assert await repo.fetch_daily("20260623") is None
- async def test_empty_rolling_returns_none(sqlite_sessionmaker) -> None:
- async with sqlite_sessionmaker() as session:
- repo = SqlAlchemyFunnelRepository(session)
- assert await repo.fetch_rolling() is None
- async def test_daily_latest_dt_is_selected(sqlite_sessionmaker) -> None:
- async with sqlite_sessionmaker() as session:
- session.add_all(
- [
- _daily_row("20260621", 100),
- _daily_row("20260623", 300),
- _daily_row("20260622", 200),
- ]
- )
- await session.commit()
- async with sqlite_sessionmaker() as session:
- repo = SqlAlchemyFunnelRepository(session)
- snapshot = await repo.fetch_daily(None)
- assert snapshot is not None
- assert snapshot.dt == "20260623"
- assert snapshot.values["uv_start"] == 300
- async def test_daily_specific_dt(sqlite_sessionmaker) -> None:
- async with sqlite_sessionmaker() as session:
- session.add_all([_daily_row("20260621", 100), _daily_row("20260623", 300)])
- await session.commit()
- async with sqlite_sessionmaker() as session:
- repo = SqlAlchemyFunnelRepository(session)
- snapshot = await repo.fetch_daily("20260621")
- assert snapshot is not None
- assert snapshot.dt == "20260621"
- assert snapshot.values["uv_start"] == 100
- async def test_daily_specific_dt_missing(sqlite_sessionmaker) -> None:
- async with sqlite_sessionmaker() as session:
- session.add(_daily_row("20260623", 300))
- await session.commit()
- async with sqlite_sessionmaker() as session:
- repo = SqlAlchemyFunnelRepository(session)
- assert await repo.fetch_daily("20200101") is None
- async def test_rolling_row_columns(sqlite_sessionmaker) -> None:
- async with sqlite_sessionmaker() as session:
- session.add(_rolling_row("20260623", top7=700, top30=3000))
- await session.commit()
- async with sqlite_sessionmaker() as session:
- repo = SqlAlchemyFunnelRepository(session)
- resp7 = await run_funnel_query(Period.last_7d, repo)
- assert resp7.data_status == DataStatus.ready
- assert resp7.snapshot_dt == "20260623"
- assert resp7.results[0].uv == 700
- resp30 = await run_funnel_query(Period.last_30d, repo)
- assert resp30.results[0].uv == 3000
|