Skip to content
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
1 change: 1 addition & 0 deletions changelog.d/1395.downstream.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added dependency on ``sphinx-tabs >= 3.5`` to organize documentation examples into tabs.
1 change: 1 addition & 0 deletions constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ setuptools-scm==9.2.2
snowballstemmer==3.0.1
sortedcontainers==2.4.0
Sphinx==8.1.3
sphinx-tabs==3.5.0
sphinx-rtd-theme==3.1.0
sphinxcontrib-applehelp==2.0.0
sphinxcontrib-devhelp==2.0.0
Expand Down
48 changes: 34 additions & 14 deletions docs/concepts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,50 @@ Assigning neighboring tests to different event loop scopes is discouraged as it
Test discovery modes
====================

Pytest-asyncio provides two modes for test discovery, *strict* and *auto*. This can be set through Pytest's ``--asyncio-mode`` command line flag, or through the configuration file:
Pytest-asyncio provides two modes for test discovery, *strict* and *auto*.
This can be set through Pytest's ``--asyncio-mode`` command line flag,
or through the configuration file.

.. code-block:: toml
.. tabs::

[tool.pytest.ini_options]
asyncio_mode = "auto" # or "strict"
.. group-tab:: Strict mode

Strict mode
-----------
.. code-block:: toml

In strict mode pytest-asyncio will only run tests that have the *asyncio* marker and will only evaluate async fixtures decorated with ``@pytest_asyncio.fixture``. Test functions and fixtures without these markers and decorators will not be handled by pytest-asyncio.
[tool.pytest.ini_options]
asyncio_mode = "strict"

This mode is intended for projects that want so support multiple asynchronous programming libraries as it allows pytest-asyncio to coexist with other async testing plugins in the same codebase.
In strict mode pytest-asyncio will only run tests that have the *asyncio* marker
and will only evaluate async fixtures decorated with ``@pytest_asyncio.fixture``.
Test functions and fixtures without these markers and decorators will not be
handled by pytest-asyncio.

Pytest automatically enables installed plugins. As a result pytest plugins need to coexist peacefully in their default configuration. This is why strict mode is the default mode.
This mode is intended for projects that want to support multiple asynchronous
programming libraries as it allows pytest-asyncio to coexist with other async
testing plugins in the same codebase.

Auto mode
---------
Pytest automatically enables installed plugins. As a result pytest plugins
need to coexist peacefully in their default configuration. This is why strict
mode is the default mode.

In *auto* mode pytest-asyncio automatically adds the *asyncio* marker to all asynchronous test functions. It will also take ownership of all async fixtures, regardless of whether they are decorated with ``@pytest.fixture`` or ``@pytest_asyncio.fixture``.
.. group-tab:: Auto mode

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.
.. code-block:: toml

If you intend to support multiple asynchronous programming libraries, e.g. *asyncio* and *trio*, strict mode will be the preferred option.
[tool.pytest.ini_options]
asyncio_mode = "auto"

In *auto* mode pytest-asyncio automatically adds the *asyncio* marker to all
asynchronous test functions. It will also take ownership of all async fixtures,
regardless of whether they are decorated with ``@pytest.fixture`` or
``@pytest_asyncio.fixture``.

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:

Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

extensions = []
extensions = ["sphinx_tabs.tabs"]

templates_path = ["_templates"]
exclude_patterns = []
Expand Down
29 changes: 17 additions & 12 deletions docs/how-to-guides/change_default_fixture_loop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,27 @@ How to change the default event loop scope of all fixtures
==========================================================
The :ref:`configuration/asyncio_default_fixture_loop_scope` configuration option sets the default event loop scope for asynchronous fixtures. The following code snippets configure all fixtures to run in a session-scoped loop by default:

.. code-block:: ini
:caption: pytest.ini
.. tabs::

[pytest]
asyncio_default_fixture_loop_scope = session
.. tab:: pytest.ini

.. code-block:: toml
:caption: pyproject.toml
.. code-block:: ini

[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "session"
[pytest]
asyncio_default_fixture_loop_scope = session

.. code-block:: ini
:caption: setup.cfg
.. tab:: pyproject.toml

[tool:pytest]
asyncio_default_fixture_loop_scope = session
.. code-block:: toml

[tool.pytest.ini_options]
asyncio_default_fixture_loop_scope = "session"

.. tab:: setup.cfg

.. code-block:: ini

[tool:pytest]
asyncio_default_fixture_loop_scope = session

Please refer to :ref:`configuration/asyncio_default_fixture_loop_scope` for other valid scopes.
32 changes: 19 additions & 13 deletions docs/how-to-guides/change_default_test_loop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,28 @@ How to change the default event loop scope of all tests
=======================================================
The :ref:`configuration/asyncio_default_test_loop_scope` configuration option sets the default event loop scope for asynchronous tests. The following code snippets configure all tests to run in a session-scoped loop by default:

.. code-block:: ini
:caption: pytest.ini
.. tabs::

[pytest]
asyncio_default_test_loop_scope = session
.. tab:: pytest.ini

.. code-block:: toml
:caption: pyproject.toml
.. code-block:: ini

[tool.pytest.ini_options]
asyncio_default_test_loop_scope = "session"
[pytest]
asyncio_default_test_loop_scope = session

.. code-block:: ini
:caption: setup.cfg
.. tab:: pyproject.toml

[tool:pytest]
asyncio_default_test_loop_scope = session
.. code-block:: toml

Please refer to :ref:`configuration/asyncio_default_test_loop_scope` for other valid scopes.
[tool.pytest.ini_options]
asyncio_default_test_loop_scope = "session"

.. tab:: setup.cfg

.. code-block:: ini

[tool:pytest]
asyncio_default_test_loop_scope = session

Please refer to :ref:`configuration/asyncio_default_test_loop_scope`
for other valid scopes.
25 changes: 16 additions & 9 deletions docs/reference/markers/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,32 @@ Markers
A coroutine or async generator with this marker is treated as a test function by pytest.
The marked function is executed as an asyncio task in the event loop provided by pytest-asyncio.

.. include:: function_scoped_loop_strict_mode_example.py
:code: python
Multiple async tests in a single class or module can be marked in different ways:

Multiple async tests in a single class or module can be marked using |pytestmark|_.
.. tabs::

.. include:: function_scoped_loop_pytestmark_strict_mode_example.py
:code: python
.. tab:: decorator

.. include:: function_scoped_loop_strict_mode_example.py
:code: python

.. tab:: pytestmark

.. include:: function_scoped_loop_pytestmark_strict_mode_example.py
:code: python

The ``pytest.mark.asyncio`` marker can be omitted entirely in |auto mode|_ where the *asyncio* marker is added automatically to *async* test functions.

By default, each test runs in it's own asyncio event loop.
By default, each test runs in its own asyncio event loop.
Multiple tests can share the same event loop by providing a *loop_scope* keyword argument to the *asyncio* mark.
The supported scopes are *function,* *class,* and *module,* *package,* and *session*.
The following code example provides a shared event loop for all tests in `TestClassScopedLoop`:
The supported scopes are *function*, *class*, *module*, *package*, and *session*.

The following code example provides a shared event loop for all tests in ``TestClassScopedLoop``:

.. include:: class_scoped_loop_strict_mode_example.py
:code: python

Similar to class-scoped event loops, a module-scoped loop is provided when setting mark's scope to *module:*
Similar to class-scoped event loops, a module-scoped loop is provided when setting mark's scope to *module*:

.. include:: module_scoped_loop_strict_mode_example.py
:code: python
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ dependencies = [
optional-dependencies.docs = [
"sphinx>=5.3",
"sphinx-rtd-theme>=1",
"sphinx-tabs>=3.5",
]
optional-dependencies.testing = [
"coverage>=6.2",
Expand Down
Loading