Skip to content

Config for default test loop_scope? #934

Closed as not planned
Closed as not planned
@BryceCicada

Description

@BryceCicada

pytest-asyncio v0.24 supports independent event-loop scopes and fixture caching scopes. This is great, thank you. However, I had some confusion while working with this. I thought I'd share in case there's an elegant solution I've not spotted.

The following works fine:

import asyncio
import pytest
import pytest_asyncio

loop: asyncio.AbstractEventLoop | None = None


@pytest_asyncio.fixture(loop_scope="session")
async def loop_fixture():
    global loop
    loop = asyncio.get_running_loop()


@pytest_asyncio.fixture(loop_scope="session", scope="function")
async def another_fixture():
    return "foo"


@pytest.mark.asyncio(loop_scope="session")
async def test_a(loop_fixture, another_fixture):
    global loop
    assert loop == asyncio.get_running_loop()
    assert another_fixture == "foo"

and with a minor change I've convinced myself that another_fixture really is function-scoped. All good.

However, if I have pyproject.toml containing:

[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "session"

my initial (hopeful) expectation was that I would not need to write loop_scope="session" everywhere, but this is mistaken:

import asyncio
import pytest
import pytest_asyncio

loop: asyncio.AbstractEventLoop | None = None


@pytest_asyncio.fixture
async def loop_fixture():
    global loop
    loop = asyncio.get_running_loop()


@pytest_asyncio.fixture(scope="function")
async def another_fixture():
    return "foo"


@pytest.mark.asyncio
async def test_a(loop_fixture, another_fixture):
    global loop
    assert loop == asyncio.get_running_loop()
    assert another_fixture == "foo"

with error:

E   pytest_asyncio.plugin.MultipleEventLoopsRequestedError: Multiple asyncio event loops with different scopes have been requested

Of course, the solution is to omit loop_scope="session" only the fixtures, but keep it on the test function itself like:

@pytest.mark.asyncio(loop_scope="session")
async def test_a(loop_fixture, another_fixture):
    ...

but in a suite of many tests, it's boilerplate.

I've understood asyncio_default_fixture_loop_scope was intended to relieve such boilerplate on the fixtures, but is there something similar possible for the tests themselves? I know I could write a hook to add this marker to the tests, but my gut feeling says this magic would confuse later. On the other hand, I could imagine some config like asyncio_default_test_loop_scope... is there something neat I've missed?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions