I was getting warnings about pytest-asyncio decorators. Here’s the fix.
Why async tests are tricky Link to heading
Async tests need an event loop to run. pytest-asyncio handles this, but there are gotchas:
- Each test gets its own event loop by default
- Fixtures need to match the test’s async-ness
- Session-scoped async fixtures are fiddly
The old way (deprecated):
@pytest.mark.asyncio
async def test_something():
result = await some_async_function()
assert result == expected
The warning says to configure asyncio_mode instead.
The fix Link to heading
In pyproject.toml:
[tool.pytest.ini_options]
asyncio_mode = "auto"
Or in pytest.ini:
[pytest]
asyncio_mode = auto
With auto mode, you don’t need the decorator anymore:
async def test_something():
result = await some_async_function()
assert result == expected
pytest-asyncio detects async test functions automatically.
Async fixtures gotchas Link to heading
Async fixtures must be used in async tests:
@pytest.fixture
async def db_connection():
conn = await create_connection()
yield conn
await conn.close()
# This works
async def test_with_db(db_connection):
await db_connection.execute("SELECT 1")
# This doesn't - can't use async fixture in sync test
def test_sync_with_db(db_connection): # Error!
...
For fixtures that need to be shared across async and sync tests, make them sync and use asyncio.run() internally.
Bulk migration Link to heading
If you have lots of tests with the old decorator, you can remove them in bulk:
rg -l '@pytest.mark.asyncio' tests/ | xargs sed -i '' '/@pytest.mark.asyncio/d'
Note: The sed syntax varies between macOS and Linux.
For general pytest tips, see pytest: last failed and specific tests.
Further reading Link to heading
- pytest-asyncio documentation - configuration options and fixture scopes