Markers

pytest.mark.asyncio

A coroutine or async generator with this marker is treated as a test function by pytest. The marked function is executed as an asyncio task in the event loop provided by pytest-asyncio.

import asyncio

import pytest


@pytest.mark.asyncio
async def test_runs_in_asyncio_event_loop():
    assert asyncio.get_running_loop()

Multiple async tests in a single class or module can be marked using pytestmark.

import asyncio

import pytest

# Marks all test coroutines in this module
pytestmark = pytest.mark.asyncio


async def test_runs_in_asyncio_event_loop():
    assert asyncio.get_running_loop()

The pytest.mark.asyncio marker can be omitted entirely in auto mode where the asyncio marker is added automatically to async test functions.

By default, each test runs in it’s own asyncio event loop. Multiple tests can share the same event loop by providing a scope keyword argument to the asyncio mark. The supported scopes are class, and module, and package. The following code example provides a shared event loop for all tests in TestClassScopedLoop:

import asyncio

import pytest


@pytest.mark.asyncio(scope="class")
class TestClassScopedLoop:
    loop: asyncio.AbstractEventLoop

    async def test_remember_loop(self):
        TestClassScopedLoop.loop = asyncio.get_running_loop()

    async def test_this_runs_in_same_loop(self):
        assert asyncio.get_running_loop() is TestClassScopedLoop.loop

Requesting class scope with the test being part of a class will give a UsageError. Similar to class-scoped event loops, a module-scoped loop is provided when setting mark’s scope to module:

import asyncio

import pytest

pytestmark = pytest.mark.asyncio(scope="module")

loop: asyncio.AbstractEventLoop


async def test_remember_loop():
    global loop
    loop = asyncio.get_running_loop()


async def test_this_runs_in_same_loop():
    global loop
    assert asyncio.get_running_loop() is loop


class TestClassA:
    async def test_this_runs_in_same_loop(self):
        global loop
        assert asyncio.get_running_loop() is loop

Package-scoped loops only work with regular Python packages. That means they require an __init__.py to be present. Package-scoped loops do not work in namespace packages. Subpackages do not share the loop with their parent package.

Tests marked with session scope share the same event loop, even if the tests exist in different packages.