You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First of all, thanks for the great pytest plugin!
Also, I like the idea of being able to specify event_loop scopes explicitly and separately to the fixture scopes.
While playing with this, I kept running into issues that my "session" scoped event_loop seemed to change between tests that were running in different files, but only if certain other tests were run...
I think this example reproduces the issues in a single file. I recognize that the docs explicitly advise against doing this, but I hope it makes the problem easier to reason about.
Here's the example.
importpytest_asyncioimportasyncioimportpytestclassFakeAsyncConnection:
def__init__(self, loop):
self.loop=loopasyncdefdo_something(self):
# Check if the current loop is the same as the one with which the# connection was createdifasyncio.get_event_loop() isnotself.loop:
raiseRuntimeError(
"This connection is being used with a different event loop!")
return"Success"@pytest_asyncio.fixture(scope="module", loop_scope="module")asyncdefasync_connection():
"""Set up a async connection object with module scope."""event_loop=asyncio.get_event_loop()
print(f"Setting up fixture: event_loop_id {id(event_loop)}")
connection=FakeAsyncConnection(event_loop)
yieldconnection@pytest.mark.asyncio(loop_scope="module")asyncdeftest_use_module_scope_loop_1(async_connection):
"""Use module loop"""print(f"Test using loop with id: {id(asyncio.get_event_loop())}")
result=awaitasync_connection.do_something()
assertresult=="Success"@pytest.mark.asyncio(loop_scope="module")asyncdeftest_use_module_scope_loop_2(async_connection):
"""Use module loop again"""print(f"Test using loop with id: {id(asyncio.get_event_loop())}")
result=awaitasync_connection.do_something()
assertresult=="Success"@pytest.mark.asyncio(loop_scope="function")asyncdeftest_use_function_scope_loop_1(async_connection):
"""Use function loop"""print(f"Test using loop with id: {id(asyncio.get_event_loop())}")
withpytest.raises(RuntimeError, match="This connection is being used with a different event loop!"):
# This should raise an error because the connection is being used with a different loopawaitasync_connection.do_something()
@pytest.mark.asyncio(loop_scope="module")asyncdeftest_use_module_scope_loop_3(async_connection):
"""Unexpectedly fail to use module scope again"""print(f"Test using loop with id: {id(asyncio.get_event_loop())}")
result=awaitasync_connection.do_something()
assertresult=="Success"
I would expect all tests to pass, however, the final test test_use_module_scope_loop_3 fails only if the test_use_function_scope_loop_1 is present. If the function scope one is commented out, the final test does pass (as expected).
The fixtures aren't obviously set up incorrectly (running with --setup-show):
SETUP S event_loop_policy
SETUP M tests/test_a.py::<event_loop> (fixtures used: event_loop_policy)
SETUP M async_connection
tests/test_a.py::test_use_module_scope_loop_1 (fixtures used: async_connection, event_loop_policy, request, tests/test_a.py::<event_loop>).
tests/test_a.py::test_use_module_scope_loop_2 (fixtures used: async_connection, event_loop_policy, request, tests/test_a.py::<event_loop>).
SETUP F event_loop
tests/test_a.py::test_use_function_scope_loop_1 (fixtures used: async_connection, event_loop, event_loop_policy, request).
TEARDOWN F event_loop
tests/test_a.py::test_use_module_scope_loop_3 (fixtures used: async_connection, event_loop_policy, request, tests/test_a.py::<event_loop>)F
TEARDOWN M async_connection
TEARDOWN M tests/test_a.py::<event_loop>
TEARDOWN S event_loop_policy
But for some reason I don't understand, the module scoped event loop changes for the last test.
The printed loop ids tell the same story... The fixture and first two tests all get the the same loop_id as expected. The function scope test gets a new one as expected. Then the final module scope test also gets a new loop_id (different from both previous loop_ids) unexpectedly.
The text was updated successfully, but these errors were encountered:
TimChild
changed the title
Requesting loop_scope="module" (or "session" etc.) returns incorrect event_loop if another fixture requests a different loop.
Requesting loop_scope="module" (or "session" etc.) returns incorrect event_loop if another function requests a different loop.
Oct 4, 2024
TimChild
changed the title
Requesting loop_scope="module" (or "session" etc.) returns incorrect event_loop if another function requests a different loop.
Requesting loop_scope="module" (or "session" etc.) returns incorrect event_loop if another test function requests a different loop.
Oct 4, 2024
Good catch and great reproducer! Thanks for the report.
The test that breaks the event loop is actually test_use_function_scope_loop_1. It uses the deprecated event_loop fixture which entails a bunch of invisible cleanups.
A fix for this should be included in a patch release for v0.24.
First of all, thanks for the great pytest plugin!
Also, I like the idea of being able to specify event_loop scopes explicitly and separately to the fixture scopes.
While playing with this, I kept running into issues that my "session" scoped event_loop seemed to change between tests that were running in different files, but only if certain other tests were run...
I think this example reproduces the issues in a single file. I recognize that the docs explicitly advise against doing this, but I hope it makes the problem easier to reason about.
Here's the example.
I would expect all tests to pass, however, the final test
test_use_module_scope_loop_3
fails only if thetest_use_function_scope_loop_1
is present. If the function scope one is commented out, the final test does pass (as expected).The fixtures aren't obviously set up incorrectly (running with
--setup-show
):But for some reason I don't understand, the module scoped event loop changes for the last test.
The printed loop ids tell the same story... The fixture and first two tests all get the the same loop_id as expected. The function scope test gets a new one as expected. Then the final module scope test also gets a new loop_id (different from both previous loop_ids) unexpectedly.
Versions:
python: 3.12.7
pytest: 8.3.3
pytest-asyncio: 0.24.0
Also, my pytest settings are:
The text was updated successfully, but these errors were encountered: