From bc92854a52b99d4b74959d9d754620f4f27c7b67 Mon Sep 17 00:00:00 2001 From: NGHTBOY Date: Thu, 25 Jun 2026 16:53:27 +0200 Subject: [PATCH] fix(tests): share one in-memory SQLite connection via StaticPool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The session-scoped integration engine used a bare `sqlite+aiosqlite:///:memory:` URL. Each pooled connection then gets its own empty in-memory database; `Base.metadata.create_all` ran on only one, so once the pool opened a second connection (concurrent sessions — e.g. a request-scoped session plus a service opening its own) that connection saw an empty DB and every subsequent test errored at setup with `sqlite3.OperationalError: no such table: users`. This intermittently broke CI (e.g. starting at test_project_cache_failed_docs.py) and gated the Heroku auto-deploy, which only fires on a green CI run on main. Use `poolclass=StaticPool` + `connect_args={"check_same_thread": False}` so the whole session-scoped engine shares a single connection — all sessions hit the same in-memory DB with the schema present. Verified: full integration suite 525 passed locally, 0 "no such table". Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/tests/integration/conftest.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/backend/tests/integration/conftest.py b/backend/tests/integration/conftest.py index 4a1693a..c9c3c03 100644 --- a/backend/tests/integration/conftest.py +++ b/backend/tests/integration/conftest.py @@ -12,6 +12,7 @@ import pytest_asyncio from httpx import ASGITransport, AsyncClient from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine +from sqlalchemy.pool import StaticPool from app.models import ( # noqa: F401 agent_learning, @@ -61,7 +62,20 @@ def event_loop(): async def engine(): from app.models.base import enable_sqlite_fk - eng = create_async_engine("sqlite+aiosqlite:///:memory:", echo=False) + # A bare ``sqlite+aiosqlite:///:memory:`` engine gives every pooled + # connection its OWN empty in-memory database. ``Base.metadata.create_all`` + # below runs on one connection, so as soon as the pool opens a second + # connection (concurrent sessions, e.g. the request-scoped session plus a + # service opening its own) that connection sees an empty DB and every + # subsequent test errors at setup with ``no such table: users``. StaticPool + # keeps a single shared connection for the whole session-scoped engine, so + # all sessions hit the same in-memory DB with the schema present. + eng = create_async_engine( + "sqlite+aiosqlite:///:memory:", + echo=False, + poolclass=StaticPool, + connect_args={"check_same_thread": False}, + ) enable_sqlite_fk(eng) # F-AUTH-01: cascade tests must exercise real FK enforcement async with eng.begin() as conn: await conn.run_sync(Base.metadata.create_all)