diff --git a/tests/conftest.py b/tests/conftest.py index 9f9cbef..f9b268a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ import pytest +import asyncio import subprocess import time import requests @@ -49,9 +50,23 @@ def app_instance() -> Generator[App, None, None]: ): app = App() yield app - # Cleanup: Ensure asyncio loop is stopped - if hasattr(app, '_loop') and app._loop.is_running(): - app._loop.call_soon_threadsafe(app._loop.stop) + # Cleanup: Ensure asyncio loop is stopped and tasks are cancelled + if hasattr(app, '_loop'): + # 1. Identify all pending tasks in app._loop. + tasks = [t for t in asyncio.all_tasks(app._loop) if not t.done()] + # 2. Cancel them using task.cancel(). + for task in tasks: + task.cancel() + # Stop background thread to take control of the loop thread-safely + if app._loop.is_running(): + app._loop.call_soon_threadsafe(app._loop.stop) + if hasattr(app, '_loop_thread') and app._loop_thread.is_alive(): + app._loop_thread.join(timeout=2.0) + # 3. Wait for them to complete using loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True)). + if tasks: + app._loop.run_until_complete(asyncio.gather(*tasks, return_exceptions=True)) + # 4. Then stop the loop. + app._loop.stop() @pytest.fixture def mock_app(app_instance: App) -> App: