Skip to content

Document test execution and parametrization #1179

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,15 @@ In *auto* mode pytest-asyncio automatically adds the *asyncio* marker to all asy
This mode is intended for projects that use *asyncio* as their only asynchronous programming library. Auto mode makes for the simplest test and fixture configuration and is the recommended default.

If you intend to support multiple asynchronous programming libraries, e.g. *asyncio* and *trio*, strict mode will be the preferred option.

.. _concepts/concurrent_execution:

Test execution and concurrency
==============================

pytest-asyncio runs async tests sequentially, just like how pytest runs synchronous tests. Each asynchronous test runs within its assigned event loop. For example, consider the following two tests:

.. include:: concepts_concurrent_execution_example.py
:code: python

This sequential execution is intentional and important for maintaining test isolation. Running tests concurrently could introduce race conditions and side effects where one test could interfere with another, making test results unreliable and difficult to debug.
16 changes: 16 additions & 0 deletions docs/concepts_concurrent_execution_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import asyncio

import pytest


@pytest.mark.asyncio
async def test_first():
await asyncio.sleep(2) # Takes 2 seconds


@pytest.mark.asyncio
async def test_second():
await asyncio.sleep(2) # Takes 2 seconds


# Total execution time: ~4 seconds, not ~2 seconds
1 change: 1 addition & 0 deletions docs/how-to-guides/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ How-To Guides
run_module_tests_in_same_loop
run_package_tests_in_same_loop
multiple_loops
parametrize_with_asyncio
uvloop
test_item_is_async

Expand Down
11 changes: 11 additions & 0 deletions docs/how-to-guides/parametrize_with_asyncio.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
=====================================
How to parametrize asynchronous tests
=====================================

The ``pytest.mark.parametrize`` marker works with asynchronous tests the same as with synchronous tests. You can apply both ``pytest.mark.asyncio`` and ``pytest.mark.parametrize`` to asynchronous test functions:

.. include:: parametrize_with_asyncio_example.py
:code: python

.. note::
Whilst asynchronous tests can be parametrized, each individual test case still runs sequentially, not concurrently. For more information about how pytest-asyncio executes tests, see :ref:`concepts/concurrent_execution`.
10 changes: 10 additions & 0 deletions docs/how-to-guides/parametrize_with_asyncio_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import asyncio

import pytest


@pytest.mark.asyncio
@pytest.mark.parametrize("value", [1, 2, 3])
async def test_parametrized_async_function(value):
await asyncio.sleep(1)
assert value > 0
Loading