Skip to content

Commit 84ec512

Browse files
committed
[feat] Raises a MultipleEventLoopsRequested error when a function-scoped loop is pulled in by an async autouse fixture in addition to an event loop with larger scope.
Signed-off-by: Michael Seifert <[email protected]>
1 parent b646cc1 commit 84ec512

File tree

3 files changed

+45
-8
lines changed

3 files changed

+45
-8
lines changed

docs/source/reference/changelog.rst

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Changelog
55
0.23.8 (UNRELEASED)
66
===================
77
- Fixes a bug that caused duplicate markers in async tests `#813 <https://github.com/pytest-dev/pytest-asyncio/issues/813>`_
8+
- Improves detection of multiple event loops being requested by the same test in strict mode `#868 <https://github.com/pytest-dev/pytest-asyncio/issues/868>`_
89

910
Known issues
1011
------------

pytest_asyncio/plugin.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -707,14 +707,6 @@ def pytest_generate_tests(metafunc: Metafunc) -> None:
707707
event_loop_fixture_id = event_loop_node.stash.get(_event_loop_fixture_id, None)
708708

709709
if event_loop_fixture_id:
710-
# This specific fixture name may already be in metafunc.argnames, if this
711-
# test indirectly depends on the fixture. For example, this is the case
712-
# when the test depends on an async fixture, both of which share the same
713-
# event loop fixture mark.
714-
if event_loop_fixture_id in metafunc.fixturenames:
715-
return
716-
fixturemanager = metafunc.config.pluginmanager.get_plugin("funcmanage")
717-
assert fixturemanager is not None
718710
if "event_loop" in metafunc.fixturenames:
719711
raise MultipleEventLoopsRequestedError(
720712
_MULTIPLE_LOOPS_REQUESTED_ERROR.format(
@@ -723,6 +715,14 @@ def pytest_generate_tests(metafunc: Metafunc) -> None:
723715
scoped_loop_node=event_loop_node.nodeid,
724716
),
725717
)
718+
# This specific fixture name may already be in metafunc.argnames, if this
719+
# test indirectly depends on the fixture. For example, this is the case
720+
# when the test depends on an async fixture, both of which share the same
721+
# event loop fixture mark.
722+
if event_loop_fixture_id in metafunc.fixturenames:
723+
return
724+
fixturemanager = metafunc.config.pluginmanager.get_plugin("funcmanage")
725+
assert fixturemanager is not None
726726
# Add the scoped event loop fixture to Metafunc's list of fixture names and
727727
# fixturedefs and leave the actual parametrization to pytest
728728
# The fixture needs to be appended to avoid messing up the fixture evaluation
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from textwrap import dedent
2+
3+
from pytest import Pytester
4+
5+
6+
def test_autouse_fixture_in_different_scope_triggers_multiple_event_loop_error(
7+
pytester: Pytester,
8+
):
9+
pytester.makepyfile(
10+
dedent(
11+
"""\
12+
import asyncio
13+
import pytest
14+
import pytest_asyncio
15+
16+
loop: asyncio.AbstractEventLoop
17+
18+
@pytest_asyncio.fixture(autouse=True)
19+
async def autouse_fixture():
20+
pass
21+
22+
@pytest_asyncio.fixture(scope="session")
23+
async def any_fixture():
24+
global loop
25+
loop = asyncio.get_running_loop()
26+
27+
@pytest.mark.asyncio(scope="session")
28+
async def test_runs_in_session_scoped_loop(any_fixture):
29+
global loop
30+
assert asyncio.get_running_loop() is loop
31+
"""
32+
)
33+
)
34+
result = pytester.runpytest("--asyncio-mode=strict")
35+
result.assert_outcomes(errors=1)
36+
result.stdout.fnmatch_lines("*MultipleEventLoopsRequestedError: *")

0 commit comments

Comments
 (0)