Session scoped event loop not actually session scope
theunkn0wn1 opened this issue · 1 comments
I am using a downstream library that requires that coroutines spawned from its objects are run on the same event loop as the library objects were instantiated on.
I intend to instantiate these library objects as async generator fixtures, to make test code super simple.
as such, I set the event loop scope to session expecting only one loop to ever be created per pytest invocation.
However, In practice the fixture is receiving a different event loop object than the test is, resulting in failure.
pytest configuration:
[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope="session"Minimum reproducible example:
from asyncio import get_running_loop
import pytest
import pytest_asyncio
@pytest.mark.asyncio
@pytest_asyncio.fixture(scope="session", loop_scope="session")
async def fx_debug() -> int:
# define a fixture that yields the ID if its event loop
loop = get_running_loop()
yield id(loop)
@pytest.mark.asyncio
async def test_assert_event_loop_is_equal(fx_debug):
# assert the ID of our event loop matches that of the fixture
assert id(get_running_loop()) == fx_debug output:
================================================================================================================================================================================================== test session starts ==================================================================================================================================================================================================
platform linux -- Python 3.12.5, pytest-8.3.3, pluggy-1.5.0
rootdir: /home/redacted/projects/redacted
configfile: pyproject.toml
plugins: asyncio-0.24.0
asyncio: mode=Mode.STRICT, default_loop_scope=session
collected 1 item
tests/test_psu_config.py F [100%]
======================================================================================================================================================================================================= FAILURES ========================================================================================================================================================================================================
____________________________________________________________________________________________________________________________________________________________________________________________ test_assert_event_loop_is_equal ____________________________________________________________________________________________________________________________________________________________________________________________
fx_debug = 137275045990176
@mark.unit_test
@mark.asyncio
async def test_assert_event_loop_is_equal(fx_debug):
> assert id(get_running_loop()) == fx_debug
E assert 137275045989840 == 137275045990176
E + where 137275045989840 = id(<_UnixSelectorEventLoop running=True closed=False debug=False>)
E + where <_UnixSelectorEventLoop running=True closed=False debug=False> = get_running_loop()
The asyncio_default_fixture_loop_scope configuration option only affects async fixtures, but not async tests.
A similar option for async tests is tracked in #793.
That means the fixture runs in a session-scoped loop, whereas the test runs the default function-scoped loop.
Adding the loop_scope="session" keyword argument to @pytest.mark.asyncio when marking the test should solve the issue.
See also: https://pytest-asyncio.readthedocs.io/en/v0.24.0/how-to-guides/run_session_tests_in_same_loop.html
Side note: @pytest.mark.asyncio has no effect on async fixtures and should be omitted.
Let me know if these pointers solve your issue!