diff --git a/changelog.d/796.fixed.rst b/changelog.d/796.fixed.rst new file mode 100644 index 00000000..6c9c8590 --- /dev/null +++ b/changelog.d/796.fixed.rst @@ -0,0 +1 @@ +Parametrized ``event_loop_policy`` fixtures no longer parametrize synchronous tests. diff --git a/pytest_asyncio/plugin.py b/pytest_asyncio/plugin.py index 38b75e41..b9fd254c 100644 --- a/pytest_asyncio/plugin.py +++ b/pytest_asyncio/plugin.py @@ -730,6 +730,7 @@ def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: metafunc.definition ) if specialized_item_class is None: + _remove_autouse_event_loop_policy_for_sync_tests(metafunc) return asyncio_marker = _resolve_asyncio_marker(metafunc.definition) @@ -788,6 +789,25 @@ def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: ) +def _remove_autouse_event_loop_policy_for_sync_tests( + metafunc: pytest.Metafunc, +) -> None: + fixture_name = event_loop_policy.__name__ + fixtureinfo = metafunc.definition._fixtureinfo + if fixture_name in fixtureinfo.argnames: + return + if any( + fixture_name in marker.args + for marker in metafunc.definition.iter_markers(name="usefixtures") + ): + return + if fixture_name in metafunc.fixturenames: + metafunc.fixturenames.remove(fixture_name) + if fixture_name in fixtureinfo.names_closure: + fixtureinfo.names_closure.remove(fixture_name) + fixtureinfo.name2fixturedefs.pop(fixture_name, None) + + @contextlib.contextmanager def _temporary_event_loop(loop: AbstractEventLoop) -> Iterator[None]: try: diff --git a/tests/markers/test_event_loop_policy.py b/tests/markers/test_event_loop_policy.py new file mode 100644 index 00000000..59246bdb --- /dev/null +++ b/tests/markers/test_event_loop_policy.py @@ -0,0 +1,40 @@ +from textwrap import dedent + +from pytest import Pytester + + +def test_parametrized_loop_policy_does_not_parametrize_sync_tests( + pytester: Pytester, +): + pytester.makeini("[pytest]\nasyncio_default_fixture_loop_scope = function") + pytester.makepyfile(dedent("""\ + import asyncio + + import pytest + + class CustomEventLoopPolicy(asyncio.DefaultEventLoopPolicy): + pass + + @pytest.fixture( + params=[ + asyncio.DefaultEventLoopPolicy(), + CustomEventLoopPolicy(), + ], + ) + def event_loop_policy(request): + return request.param + + @pytest.mark.asyncio + async def test_async(): + assert isinstance( + asyncio.get_event_loop_policy(), + (asyncio.DefaultEventLoopPolicy, CustomEventLoopPolicy), + ) + + def test_sync(): + assert True + """)) + + result = pytester.runpytest("--asyncio-mode=strict") + + result.assert_outcomes(passed=3)