Skip to content

Fix event_loop_policy parametrization scope#1454

Open
puneetdixit200 wants to merge 2 commits into
pytest-dev:mainfrom
puneetdixit200:fix/796-event-loop-policy
Open

Fix event_loop_policy parametrization scope#1454
puneetdixit200 wants to merge 2 commits into
pytest-dev:mainfrom
puneetdixit200:fix/796-event-loop-policy

Conversation

@puneetdixit200
Copy link
Copy Markdown

Summary

  • stop making the default event_loop_policy fixture autouse
  • request event_loop_policy only for pytest-asyncio tests and tests using asyncio fixtures, so plain sync tests are not parametrized
  • add regression coverage for plain sync tests and sync tests that use asyncio fixtures
  • avoid re-importing pytest_asyncio in one subprocess test under -W error; the entry point already loads the plugin

Fixes #796

Tests

  • .venv/bin/python -m pytest -q
  • .venv/bin/python -m pytest tests/test_set_event_loop.py::test_asyncio_run_after_async_fixture_does_not_leak_loop tests/markers/test_function_scope.py::test_parametrized_loop_policy_does_not_parametrize_sync_tests tests/markers/test_function_scope.py::test_parametrized_loop_policy_parametrizes_sync_tests_with_async_fixtures -q
  • .venv/bin/python -m pytest tests/markers/test_function_scope.py tests/markers/test_module_scope.py tests/markers/test_class_scope.py tests/markers/test_session_scope.py tests/test_loop_factory_parametrization.py tests/test_asyncio_fixture.py -q
  • .venv/bin/python -m ruff check pytest_asyncio/plugin.py tests/markers/test_function_scope.py tests/test_set_event_loop.py
  • .venv/bin/python -m mypy --python-version 3.13 pytest_asyncio/
  • .venv/bin/python -m pyright --pythonpath .venv/bin/python --pythonversion 3.13 pytest_asyncio/
  • git diff --check

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented May 21, 2026

Codecov Report

❌ Patch coverage is 85.18519% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.00%. Comparing base (9190447) to head (8305b3a).

Files with missing lines Patch % Lines
pytest_asyncio/plugin.py 85.18% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1454      +/-   ##
==========================================
- Coverage   94.50%   94.00%   -0.51%     
==========================================
  Files           2        2              
  Lines         510      534      +24     
  Branches       62       69       +7     
==========================================
+ Hits          482      502      +20     
- Misses         22       24       +2     
- Partials        6        8       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@golikovichev golikovichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach looks clean. Dropping autouse=True from the event_loop_policy fixture and gating its injection on pytest_generate_tests only when the test uses asyncio fixtures (or is async itself) is the right shape to fix #796 without breaking the loop-policy parametrization use case.

Two observations from a downstream-user read:

  1. _uses_asyncio_fixtures walks metafunc._arg2fixturedefs and short-circuits on first match. In AUTO mode it falls back to _is_coroutine_or_asyncgen, which is what catches sync tests that happen to request async fixtures - exactly the gap #796 surfaced. Worth keeping the AUTO branch as-is even though it adds a per-fixture check.
  2. The negative-case regression test test_parametrized_loop_policy_does_not_parametrize_sync_tests is paired with test_parametrized_loop_policy_parametrizes_sync_tests_with_async_fixtures (positive case). Good coverage pattern.

CI green across the full matrix (Py 3.10-3.14 + Windows + pytest main). Lint + mypy + pyright also clean per PR body.

Not a maintainer, leaving this as a non-blocking review.

Comment thread pytest_asyncio/plugin.py
)


def _add_fixture_to_metafunc(metafunc: pytest.Metafunc, fixture_name: str) -> None:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this changes pytest's internals and breaks valid usage. For example, on main, this passes.

$ cat >mre.py <<'# EOF'
import asyncio
import pytest


@pytest.fixture(params=[asyncio.DefaultEventLoopPolicy(), asyncio.DefaultEventLoopPolicy()])
def policy(request):
    return request.param


@pytest.fixture
def event_loop_policy(policy):
    return policy


@pytest.mark.asyncio
async def test_async():
    pass


async def test_sync():
    pass
# EOF

$ pytest mre.py
==================================================== test session starts ====================================================
platform darwin -- Python 3.13.0, pytest-9.0.3, pluggy-1.6.0
rootdir: /Users/tjkuson/workspace/pytest-asyncio
configfile: pyproject.toml
plugins: asyncio-1.4.0a3.dev24
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collected 2 items

mre.py EE                                                                                                             [100%]

========================================================== ERRORS ===========================================================
_______________________________________________ ERROR at setup of test_async ________________________________________________
The requested fixture has no parameter defined for test:
    mre.py::test_async

Requested fixture 'policy' defined in:
mre.py:6

Requested here:
.venv/lib/python3.13/site-packages/_pytest/fixtures.py:627
________________________________________________ ERROR at setup of test_sync ________________________________________________
The requested fixture has no parameter defined for test:
    mre.py::test_sync

Requested fixture 'policy' defined in:
mre.py:6

Requested here:
.venv/lib/python3.13/site-packages/_pytest/fixtures.py:627
===================================================== 2 errors in 0.02s =====================================================

Copy link
Copy Markdown

@golikovichev golikovichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch with the MRE. My read was too superficial - I focused on the autouse change and the regression test pair, but missed that _add_fixture_to_metafunc injecting event_loop_policy breaks valid fixture chains where event_loop_policy depends on another parametrized fixture (like your policy). The patch shifts the parametrization origin out from under pytest's resolver.

Leaving this to the PR author and maintainers.

Copy link
Copy Markdown

@golikovichev golikovichev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed after 8305b3a. The new _add_fixture_to_metafunc walks the closure via fixturemanager.getfixtureclosure() instead of attaching just the named fixture, so parametrize chains like event_loop_policy(policy) from @tjkuson's MRE are now preserved end to end.

The new test test_parametrized_loop_policy_can_depend_on_parametrized_fixture mirrors the MRE shape directly (parametrized policy fixture, event_loop_policy(policy) depending on it, both async and sync tests), so the regression is pinned. The two surrounding sync-vs-async parametrization tests cover the adjacent cases I would have asked for, so I do not have anything to add.

Sorry again for missing this in my first read - your MRE made the failure mode obvious, and the fix landed cleanly.

gmail-precheck-done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parametrizing event_loop_policy parametrizes all tests

4 participants