diff --git a/docs/concepts.rst b/docs/concepts.rst index a25df036..591059a8 100644 --- a/docs/concepts.rst +++ b/docs/concepts.rst @@ -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. diff --git a/docs/concepts_concurrent_execution_example.py b/docs/concepts_concurrent_execution_example.py new file mode 100644 index 00000000..e573ca27 --- /dev/null +++ b/docs/concepts_concurrent_execution_example.py @@ -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 diff --git a/docs/how-to-guides/index.rst b/docs/how-to-guides/index.rst index 04276256..2dadc881 100644 --- a/docs/how-to-guides/index.rst +++ b/docs/how-to-guides/index.rst @@ -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 diff --git a/docs/how-to-guides/parametrize_with_asyncio.rst b/docs/how-to-guides/parametrize_with_asyncio.rst new file mode 100644 index 00000000..b965cb7d --- /dev/null +++ b/docs/how-to-guides/parametrize_with_asyncio.rst @@ -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`. diff --git a/docs/how-to-guides/parametrize_with_asyncio_example.py b/docs/how-to-guides/parametrize_with_asyncio_example.py new file mode 100644 index 00000000..54f181be --- /dev/null +++ b/docs/how-to-guides/parametrize_with_asyncio_example.py @@ -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