pytest-asyncio

raw JSON →
1.3.0 verified Tue May 12 auth: no python install: verified quickstart: verified

pytest plugin for testing asyncio code. Required for async def test_ functions — pytest does not run them natively. Has undergone multiple breaking redesigns around event loop scoping. Current version is 1.3.0 (2026). Has a long history of yanked releases and sudden breaking changes.

pip install pytest-asyncio
error RuntimeWarning: coroutine 'test_example' was never awaited
cause `pytest` attempts to run an `async def` test function as a regular function because `pytest-asyncio` is not installed or correctly configured to manage async tests.
fix
Install pytest-asyncio (pip install pytest-asyncio). The plugin automatically detects and runs async def tests.
error RuntimeError: There is no current event loop in thread 'main'
cause An asynchronous function or coroutine is being called or awaited outside an active `asyncio` event loop managed by `pytest-asyncio`.
fix
Ensure all async operations are performed within async def test functions or async fixtures properly managed by pytest-asyncio.
error pytest_asyncio.plugin.ScopeMismatch
cause An `asyncio`-scoped fixture depends on or is configured with a scope incompatible with another `asyncio`-scoped fixture it interacts with.
fix
Review the scopes of pytest_asyncio.fixture definitions, ensuring dependent fixtures have compatible scopes (e.g., a session-scoped fixture cannot depend on a function-scoped fixture).
error DeprecationWarning: The `loop` fixture is deprecated. Use `anyio_backend` or `asyncio_mode` instead.
cause The test suite or fixtures are explicitly using the `loop` fixture, which has been deprecated in newer `pytest-asyncio` versions in favor of more modern event loop management, often via `anyio`.
fix
Remove explicit usage of the loop fixture. pytest-asyncio typically manages the event loop implicitly for async def tests. For explicit backend control, use the anyio_backend fixture or configure asyncio_mode in pytest.ini.
breaking asyncio_mode must be explicitly set. There is no safe default — omitting it causes a DeprecationWarning and the default changed from 'legacy' to 'strict' in 0.21. LLM-generated configs often omit this entirely.
fix Add to pytest.ini: [pytest]\nasyncio_mode = auto\n\nOr use strict mode and mark every test with @pytest.mark.asyncio.
breaking legacy mode removed in 0.23. Any codebase relying on asyncio_mode=legacy (the old default) will fail after upgrading past 0.21.
fix Migrate to asyncio_mode=auto (least friction) or asyncio_mode=strict (explicit marks required).
breaking Custom event_loop fixture redefinition removed in 1.x. A very common pattern in older tutorials — defining a session-scoped event_loop fixture — now raises an error.
fix Use the loop_scope argument on @pytest.mark.asyncio or @pytest_asyncio.fixture instead: @pytest_asyncio.fixture(loop_scope='session'). For custom event loop policies, use the event_loop_policy fixture.
breaking @pytest.asyncio_event_loop mark removed. Was used for class/module-scoped event loops.
fix Use @pytest.mark.asyncio(loop_scope='module') or @pytest.mark.asyncio(loop_scope='class') instead.
gotcha Async fixtures must use @pytest_asyncio.fixture, not @pytest.fixture. Using @pytest.fixture on an async function works in auto mode but emits warnings and fails in strict mode.
fix Always use @pytest_asyncio.fixture for async fixtures regardless of mode.
gotcha async def test_ functions silently appear to pass without actually running in strict mode if @pytest.mark.asyncio is missing. No error is raised — the test is collected and marked as passed.
fix Use asyncio_mode=auto to avoid per-test marks, or ensure every async test has @pytest.mark.asyncio in strict mode.
gotcha Several versions in the 0.22-0.24 range were yanked from PyPI due to fundamental event loop scoping bugs. Pinning to a yanked version will fail at install time.
fix Use 1.x (current stable). If pinning, verify the specific version is not yanked on PyPI.
gotcha Test output contains pip-specific warnings/notices (e.g., about running as root or available updates). These are external to pytest-asyncio's behavior.
fix Address pip warnings according to pip's recommendations, such as using a virtual environment or updating pip, if desired. This output does not indicate a pytest-asyncio specific failure.
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.48s 30.6M
3.10 slim (glibc) - - 0.33s 31M
3.11 alpine (musl) - - 0.68s 33.8M
3.11 slim (glibc) - - 0.54s 34M
3.12 alpine (musl) - - 0.82s 25.4M
3.12 slim (glibc) - - 0.81s 26M
3.13 alpine (musl) - - 0.81s 24.7M
3.13 slim (glibc) - - 0.75s 25M
3.9 alpine (musl) - - 0.44s 30.0M
3.9 slim (glibc) - - 0.41s 30M

asyncio_mode must be configured. Use @pytest_asyncio.fixture for async fixtures.

# pytest.ini or pyproject.toml — REQUIRED configuration
# [pytest]
# asyncio_mode = auto

# With asyncio_mode=auto, no per-test marks needed:
import pytest_asyncio

@pytest_asyncio.fixture
async def async_client():
    client = await create_client()
    yield client
    await client.close()

async def test_something(async_client):
    result = await async_client.fetch()
    assert result is not None

# Without asyncio_mode=auto, mark each test explicitly:
import pytest

@pytest.mark.asyncio
async def test_explicit():
    await asyncio.sleep(0)