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 Common errors
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. Warnings
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.
Install compatibility verified last tested: 2026-05-12
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
Imports
- pytest_asyncio.fixture wrong
@pytest.fixture async def my_async_fixture(): return await setup_something() # silently broken in strict modecorrectimport pytest_asyncio @pytest_asyncio.fixture async def my_async_fixture(): return await setup_something() - asyncio mark wrong
async def test_something(): await asyncio.sleep(0) # silently passes without running in strict modecorrect@pytest.mark.asyncio async def test_something(): await asyncio.sleep(0)
Quickstart verified last tested: 2026-04-23
# 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)