From 402b25f4188016b81cc10a147010014af920c6a2 Mon Sep 17 00:00:00 2001 From: Jason Staack Date: Sun, 15 Mar 2026 06:42:30 -0500 Subject: [PATCH] fix(ci): use module-level engines to avoid event loop teardown crash Per-test engine creation/disposal triggers asyncpg event loop errors during pytest-asyncio teardown. Module-level engines are created once and reused across all tests. Co-Authored-By: Claude Opus 4.6 (1M context) --- backend/tests/integration/conftest.py | 37 ++++++++++++--------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/backend/tests/integration/conftest.py b/backend/tests/integration/conftest.py index 2efe019..ecbcd81 100644 --- a/backend/tests/integration/conftest.py +++ b/backend/tests/integration/conftest.py @@ -92,30 +92,27 @@ def setup_database(): # --------------------------------------------------------------------------- -@pytest_asyncio.fixture -async def admin_engine(): +# Module-level engines — created once, reused across all tests. +# Avoids per-test engine creation/disposal which triggers asyncpg +# event loop issues during pytest-asyncio teardown. +_admin_engine = create_async_engine( + TEST_DATABASE_URL, echo=False, pool_pre_ping=True, pool_size=5, max_overflow=5 +) +_app_engine = create_async_engine( + TEST_APP_USER_DATABASE_URL, echo=False, pool_pre_ping=True, pool_size=5, max_overflow=5 +) + + +@pytest.fixture +def admin_engine(): """Admin engine (superuser) -- bypasses RLS.""" - engine = create_async_engine( - TEST_DATABASE_URL, echo=False, pool_pre_ping=True, pool_size=5, max_overflow=5 - ) - yield engine - try: - await engine.dispose() - except RuntimeError: - pass # Event loop may be closed during final teardown + return _admin_engine -@pytest_asyncio.fixture -async def app_engine(): +@pytest.fixture +def app_engine(): """App-user engine -- RLS enforced.""" - engine = create_async_engine( - TEST_APP_USER_DATABASE_URL, echo=False, pool_pre_ping=True, pool_size=5, max_overflow=5 - ) - yield engine - try: - await engine.dispose() - except RuntimeError: - pass # Event loop may be closed during final teardown + return _app_engine # ---------------------------------------------------------------------------