refactor(tests): add temp sqlite helper (#2930)

This commit is contained in:
Alexandre Teixeira
2026-06-07 22:44:16 +01:00
committed by GitHub
parent 9ad6a2809e
commit a017108d41
5 changed files with 45 additions and 36 deletions
+10
View File
@@ -72,6 +72,16 @@ Use only for the guarded fake/stub `src.endpoint_resolver` cleanup pattern.
cached against them. cached against them.
- Accepts explicit extra dependent module names to evict alongside the defaults. - Accepts explicit extra dependent module names to evict alongside the defaults.
### `tests.helpers.sqlite_db.make_temp_sqlite`
Use for the repeated file-backed temp sqlite setup in tests.
- Only constructs `(SessionLocal, engine, tmpfile)` from the repeated block.
- Does not patch modules and does not clean up the temp file.
- The caller must bind `SessionLocal` explicitly onto whatever module the code
under test reads, and must keep the returned objects alive.
- Do not use it as a general DB fixture framework.
## What not to abstract yet ## What not to abstract yet
Some remaining patterns should stay as-is for now rather than being forced into Some remaining patterns should stay as-is for now rather than being forced into
+29
View File
@@ -0,0 +1,29 @@
"""Construct a file-backed temp sqlite DB for tests.
Only builds the SQLAlchemy objects from the repeated temp-sqlite block. It
does not patch modules, manage cleanup, or own any global state — the caller
keeps the returned objects alive and binds ``SessionLocal`` where needed.
"""
import tempfile
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
def make_temp_sqlite(metadata):
"""Build a file-backed temp sqlite database and create its tables.
Returns ``(SessionLocal, engine, tmpfile)``. The caller must keep these
references alive (temp file and engine GC are the caller's concern) and
bind ``SessionLocal`` onto whatever module the code under test reads.
"""
tmpfile = tempfile.NamedTemporaryFile(suffix=".db", delete=False)
engine = create_engine(
f"sqlite:///{tmpfile.name}",
connect_args={"check_same_thread": False},
poolclass=NullPool,
)
metadata.create_all(engine)
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False)
return SessionLocal, engine, tmpfile
+2 -12
View File
@@ -7,29 +7,19 @@ calling do_manage_calendar with an rrule stores a single event carrying that RRU
import json import json
import sys import sys
import tempfile
import uuid import uuid
import pytest import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
from tests.helpers.import_state import clear_fake_database_modules from tests.helpers.import_state import clear_fake_database_modules
from tests.helpers.sqlite_db import make_temp_sqlite
clear_fake_database_modules() clear_fake_database_modules()
import core.database as cdb import core.database as cdb
from core.database import CalendarEvent from core.database import CalendarEvent
_TMPDB = tempfile.NamedTemporaryFile(suffix=".db", delete=False) _TS, _ENGINE, _TMPDB = make_temp_sqlite(cdb.Base.metadata)
_ENGINE = create_engine(
f"sqlite:///{_TMPDB.name}",
connect_args={"check_same_thread": False},
poolclass=NullPool,
)
cdb.Base.metadata.create_all(_ENGINE)
_TS = sessionmaker(bind=_ENGINE, autoflush=False, autocommit=False)
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
+2 -12
View File
@@ -9,25 +9,15 @@ Tokyo user) and left is_utc inconsistent. The do_manage_notes update path
was already fixed for the analogous issue. was already fixed for the analogous issue.
""" """
import json import json
import tempfile
import uuid import uuid
import pytest import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
import core.database as cdb import core.database as cdb
from core.database import CalendarEvent from core.database import CalendarEvent
from tests.helpers.sqlite_db import make_temp_sqlite
_TMPDB = tempfile.NamedTemporaryFile(suffix=".db", delete=False) _TS, _ENGINE, _TMPDB = make_temp_sqlite(cdb.Base.metadata)
_ENGINE = create_engine(
f"sqlite:///{_TMPDB.name}",
connect_args={"check_same_thread": False},
poolclass=NullPool,
)
cdb.Base.metadata.create_all(_ENGINE)
_TS = sessionmaker(bind=_ENGINE, autoflush=False, autocommit=False)
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
+2 -12
View File
@@ -10,26 +10,16 @@ back as a corrupted string blob - the attachment was destroyed. The
sibling _persist_message json.dumps-es list content; replace_messages did sibling _persist_message json.dumps-es list content; replace_messages did
not. not.
""" """
import tempfile
import uuid import uuid
import pytest import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.pool import NullPool
import core.database as cdb import core.database as cdb
from core.database import Session as DbSession from core.database import Session as DbSession
from core.models import ChatMessage from core.models import ChatMessage
from tests.helpers.sqlite_db import make_temp_sqlite
_TMPDB = tempfile.NamedTemporaryFile(suffix=".db", delete=False) _TS, _ENGINE, _TMPDB = make_temp_sqlite(cdb.Base.metadata)
_ENGINE = create_engine(
f"sqlite:///{_TMPDB.name}",
connect_args={"check_same_thread": False},
poolclass=NullPool,
)
cdb.Base.metadata.create_all(_ENGINE)
_TS = sessionmaker(bind=_ENGINE, autoflush=False, autocommit=False)
@pytest.fixture @pytest.fixture