pytest-dev / pytest-dev/pytest-asyncio

Loop factory parametrization tears down async fixtures used by sync tests

Open
#1,501 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
1.7k
Forks
207
Avg merge
5h 35m
Merged PRs (30d)
9

Description

I encountered an issue with defining pytest_asyncio_loop_factories in test suites where non-async tests use async fixtures in shared loop scopes.

To reproduce:

# conftest.py

import asyncio
from collections.abc import Mapping, Callable

import pytest


def pytest_asyncio_loop_factories(
    config: pytest.Config,
    item: pytest.Item,
) -> Mapping[str, Callable[[], asyncio.AbstractEventLoop]]:
    return {"default": asyncio.new_event_loop}
# test_mre.py

from collections.abc import AsyncGenerator

import pytest
import pytest_asyncio


@pytest_asyncio.fixture(scope="session")
async def parent() -> AsyncGenerator[str]:
    yield "parent"


@pytest_asyncio.fixture(scope="session")
async def child(parent: str) -> AsyncGenerator[str]:
    yield "child"


@pytest.mark.asyncio(loop_scope="session")
async def test_async(parent) -> None:
    assert parent == "parent"


def test_sync(child: str) -> None:
    assert child == "child"

Running test_mre.py on the above using pytest-asyncio 1.4.0 and pytest 9.1.1 shows one pass and one failure with the following errror:

AssertionError: The fixture value for "parent" is not available.  This can happen when the fixture has already been torn down.

If pytest_asyncio_loop_factories is not defined in the conftest file, both tests pass.

If test_async is after test_sync, both tests pass.

The expected behaviour is that both tests pass regardless of order and pytest_asyncio_loop_factories hook implementation.

I think the fix would involve handling the loop factory for any test item that uses a pytest-asyncio-managed async fixture, not just async tests themselves.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the conftest.py hook and reproduce the failure using test_mre.py under pytest-asyncio 1.4.0 and pytest 9.1.1, testing both test orders. Trace how pytest_asyncio_loop_factories interacts with the session-scoped parent and child fixtures; done means both tests pass regardless of order when the hook is defined.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.