Skip to content

Commit 56a393a

Browse files
authored
Simplify README, move most content to a separate user documentation. (#448)
Signed-off-by: Michael Seifert <[email protected]> Signed-off-by: Michael Seifert <[email protected]>
1 parent 3c78732 commit 56a393a

File tree

9 files changed

+328
-204
lines changed

9 files changed

+328
-204
lines changed

Diff for: README.rst

+9-204
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
pytest-asyncio: pytest support for asyncio
2-
==========================================
1+
pytest-asyncio
2+
==============
33

44
.. image:: https://img.shields.io/pypi/v/pytest-asyncio.svg
55
:target: https://pypi.python.org/pypi/pytest-asyncio
@@ -13,12 +13,9 @@ pytest-asyncio: pytest support for asyncio
1313
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
1414
:target: https://github.com/ambv/black
1515

16-
pytest-asyncio is an Apache2 licensed library, written in Python, for testing
17-
asyncio code with pytest.
16+
pytest-asyncio is a `pytest <https://docs.pytest.org/en/latest/contents.html>`_ plugin. It facilitates testing of code that uses the `asyncio <https://docs.python.org/3/library/asyncio.html>`_ library.
1817

19-
asyncio code is usually written in the form of coroutines, which makes it
20-
slightly more difficult to test using normal testing tools. pytest-asyncio
21-
provides useful fixtures and markers to make testing easier.
18+
Specifically, pytest-asyncio provides support for coroutines as test functions. This allows users to *await* code inside their tests. For example, the following code is executed as a test item by pytest:
2219

2320
.. code-block:: python
2421
@@ -27,21 +24,14 @@ provides useful fixtures and markers to make testing easier.
2724
res = await library.do_something()
2825
assert b"expected result" == res
2926
30-
pytest-asyncio has been strongly influenced by pytest-tornado_.
3127
32-
.. _pytest-tornado: https://github.com/eugeniy/pytest-tornado
28+
Note that test classes subclassing the standard `unittest <https://docs.python.org/3/library/unittest.html>`__ library are not supported. Users
29+
are advised to use `unittest.IsolatedAsyncioTestCase <https://docs.python.org/3/library/unittest.html#unittest.IsolatedAsyncioTestCase>`__
30+
or an async framework such as `asynctest <https://asynctest.readthedocs.io/en/latest>`__.
31+
3332

34-
Features
35-
--------
33+
pytest-asyncio is available under the `Apache License 2.0 <https://github.com/pytest-dev/pytest-asyncio/blob/master/LICENSE>`_.
3634

37-
- fixtures for creating and injecting versions of the asyncio event loop
38-
- fixtures for injecting unused tcp/udp ports
39-
- pytest markers for treating tests as asyncio coroutines
40-
- easy testing with non-default event loops
41-
- support for `async def` fixtures and async generator fixtures
42-
- support *auto* mode to handle all async fixtures and tests automatically by asyncio;
43-
provide *strict* mode if a test suite should work with different async frameworks
44-
simultaneously, e.g. ``asyncio`` and ``trio``.
4535

4636
Installation
4737
------------
@@ -54,191 +44,6 @@ To install pytest-asyncio, simply:
5444
5545
This is enough for pytest to pick up pytest-asyncio.
5646

57-
Modes
58-
-----
59-
60-
Pytest-asyncio provides two modes: *auto* and *strict* with *strict* mode being the default.
61-
62-
The mode can be set by ``asyncio_mode`` configuration option in `configuration file
63-
<https://docs.pytest.org/en/latest/reference/customize.html>`_:
64-
65-
.. code-block:: ini
66-
67-
# pytest.ini
68-
[pytest]
69-
asyncio_mode = auto
70-
71-
The value can be overridden by command-line option for ``pytest`` invocation:
72-
73-
.. code-block:: bash
74-
75-
$ pytest tests --asyncio-mode=strict
76-
77-
Auto mode
78-
~~~~~~~~~
79-
80-
When the mode is auto, all discovered *async* tests are considered *asyncio-driven* even
81-
if they have no ``@pytest.mark.asyncio`` marker.
82-
83-
All async fixtures are considered *asyncio-driven* as well, even if they are decorated
84-
with a regular ``@pytest.fixture`` decorator instead of dedicated
85-
``@pytest_asyncio.fixture`` counterpart.
86-
87-
*asyncio-driven* means that tests and fixtures are executed by ``pytest-asyncio``
88-
plugin.
89-
90-
This mode requires the simplest tests and fixtures configuration and is
91-
recommended for default usage *unless* the same project and its test suite should
92-
execute tests from different async frameworks, e.g. ``asyncio`` and ``trio``. In this
93-
case, auto-handling can break tests designed for other framework; please use *strict*
94-
mode instead.
95-
96-
Strict mode
97-
~~~~~~~~~~~
98-
99-
Strict mode enforces ``@pytest.mark.asyncio`` and ``@pytest_asyncio.fixture`` usage.
100-
Without these markers, tests and fixtures are not considered as *asyncio-driven*, other
101-
pytest plugin can handle them.
102-
103-
Please use this mode if multiple async frameworks should be combined in the same test
104-
suite.
105-
106-
This mode is used by default for the sake of project inter-compatibility.
107-
108-
109-
Fixtures
110-
--------
111-
112-
``event_loop``
113-
~~~~~~~~~~~~~~
114-
Creates a new asyncio event loop based on the current event loop policy. The new loop
115-
is available as the return value of this fixture or via `asyncio.get_running_loop <https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.get_running_loop>`__.
116-
The event loop is closed when the fixture scope ends. The fixture scope defaults
117-
to ``function`` scope.
118-
119-
Note that just using the ``event_loop`` fixture won't make your test function
120-
a coroutine. You'll need to interact with the event loop directly, using methods
121-
like ``event_loop.run_until_complete``. See the ``pytest.mark.asyncio`` marker
122-
for treating test functions like coroutines.
123-
124-
.. code-block:: python
125-
126-
def test_http_client(event_loop):
127-
url = "http://httpbin.org/get"
128-
resp = event_loop.run_until_complete(http_client(url))
129-
assert b"HTTP/1.1 200 OK" in resp
130-
131-
The ``event_loop`` fixture can be overridden in any of the standard pytest locations,
132-
e.g. directly in the test file, or in ``conftest.py``. This allows redefining the
133-
fixture scope, for example:
134-
135-
.. code-block:: python
136-
137-
@pytest.fixture(scope="session")
138-
def event_loop():
139-
policy = asyncio.get_event_loop_policy()
140-
loop = policy.new_event_loop()
141-
yield loop
142-
loop.close()
143-
144-
If you need to change the type of the event loop, prefer setting a custom event loop policy over redefining the ``event_loop`` fixture.
145-
146-
If the ``pytest.mark.asyncio`` marker is applied to a test function, the ``event_loop``
147-
fixture will be requested automatically by the test function.
148-
149-
``unused_tcp_port``
150-
~~~~~~~~~~~~~~~~~~~
151-
Finds and yields a single unused TCP port on the localhost interface. Useful for
152-
binding temporary test servers.
153-
154-
``unused_tcp_port_factory``
155-
~~~~~~~~~~~~~~~~~~~~~~~~~~~
156-
A callable which returns a different unused TCP port each invocation. Useful
157-
when several unused TCP ports are required in a test.
158-
159-
.. code-block:: python
160-
161-
def a_test(unused_tcp_port_factory):
162-
port1, port2 = unused_tcp_port_factory(), unused_tcp_port_factory()
163-
...
164-
165-
``unused_udp_port`` and ``unused_udp_port_factory``
166-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167-
Work just like their TCP counterparts but return unused UDP ports.
168-
169-
170-
Async fixtures
171-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
172-
Asynchronous fixtures are defined just like ordinary pytest fixtures, except they should be decorated with ``@pytest_asyncio.fixture``.
173-
174-
.. code-block:: python3
175-
176-
import pytest_asyncio
177-
178-
179-
@pytest_asyncio.fixture
180-
async def async_gen_fixture():
181-
await asyncio.sleep(0.1)
182-
yield "a value"
183-
184-
185-
@pytest_asyncio.fixture(scope="module")
186-
async def async_fixture():
187-
return await asyncio.sleep(0.1)
188-
189-
All scopes are supported, but if you use a non-function scope you will need
190-
to redefine the ``event_loop`` fixture to have the same or broader scope.
191-
Async fixtures need the event loop, and so must have the same or narrower scope
192-
than the ``event_loop`` fixture.
193-
194-
*auto* mode automatically converts async fixtures declared with the
195-
standard ``@pytest.fixture`` decorator to *asyncio-driven* versions.
196-
197-
198-
Markers
199-
-------
200-
201-
``pytest.mark.asyncio``
202-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
203-
Mark your test coroutine with this marker and pytest will execute it as an
204-
asyncio task using the event loop provided by the ``event_loop`` fixture. See
205-
the introductory section for an example.
206-
207-
The event loop used can be overridden by overriding the ``event_loop`` fixture
208-
(see above).
209-
210-
In order to make your test code a little more concise, the pytest |pytestmark|_
211-
feature can be used to mark entire modules or classes with this marker.
212-
Only test coroutines will be affected (by default, coroutines prefixed by
213-
``test_``), so, for example, fixtures are safe to define.
214-
215-
.. code-block:: python
216-
217-
import asyncio
218-
219-
import pytest
220-
221-
# All test coroutines will be treated as marked.
222-
pytestmark = pytest.mark.asyncio
223-
224-
225-
async def test_example(event_loop):
226-
"""No marker!"""
227-
await asyncio.sleep(0, loop=event_loop)
228-
229-
In *auto* mode, the ``pytest.mark.asyncio`` marker can be omitted, the marker is added
230-
automatically to *async* test functions.
231-
232-
233-
.. |pytestmark| replace:: ``pytestmark``
234-
.. _pytestmark: http://doc.pytest.org/en/latest/example/markers.html#marking-whole-classes-or-modules
235-
236-
Note about unittest
237-
-------------------
238-
239-
Test classes subclassing the standard `unittest <https://docs.python.org/3/library/unittest.html>`__ library are not supported, users
240-
are recommended to use `unittest.IsolatedAsyncioTestCase <https://docs.python.org/3/library/unittest.html#unittest.IsolatedAsyncioTestCase>`__
241-
or an async framework such as `asynctest <https://asynctest.readthedocs.io/en/latest>`__.
24247

24348
Contributing
24449
------------

Diff for: docs/Makefile

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Minimal makefile for Sphinx documentation
2+
#
3+
4+
# You can set these variables from the command line, and also
5+
# from the environment for the first two.
6+
SPHINXOPTS ?=
7+
SPHINXBUILD ?= sphinx-build
8+
SOURCEDIR = source
9+
BUILDDIR = build
10+
11+
# Put it first so that "make" without argument is like "make help".
12+
help:
13+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14+
15+
.PHONY: help Makefile
16+
17+
# Catch-all target: route all unknown targets to Sphinx using the new
18+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19+
%: Makefile
20+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

Diff for: docs/make.bat

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
@ECHO OFF
2+
3+
pushd %~dp0
4+
5+
REM Command file for Sphinx documentation
6+
7+
if "%SPHINXBUILD%" == "" (
8+
set SPHINXBUILD=sphinx-build
9+
)
10+
set SOURCEDIR=source
11+
set BUILDDIR=build
12+
13+
%SPHINXBUILD% >NUL 2>NUL
14+
if errorlevel 9009 (
15+
echo.
16+
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
17+
echo.installed, then set the SPHINXBUILD environment variable to point
18+
echo.to the full path of the 'sphinx-build' executable. Alternatively you
19+
echo.may add the Sphinx directory to PATH.
20+
echo.
21+
echo.If you don't have Sphinx installed, grab it from
22+
echo.https://www.sphinx-doc.org/
23+
exit /b 1
24+
)
25+
26+
if "%1" == "" goto help
27+
28+
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29+
goto end
30+
31+
:help
32+
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33+
34+
:end
35+
popd

Diff for: docs/source/concepts.rst

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
========
2+
Concepts
3+
========
4+
5+
asyncio event loops
6+
===================
7+
pytest-asyncio runs each test item in its own asyncio event loop. The loop can be accessed via the ``event_loop`` fixture, which is automatically requested by all async tests.
8+
9+
.. code-block:: python
10+
11+
async def test_provided_loop_is_running_loop(event_loop):
12+
assert event_loop is asyncio.get_running_loop()
13+
14+
You can think of `event_loop` as an autouse fixture for async tests.
15+
16+
Test discovery modes
17+
====================
18+
19+
Pytest-asyncio provides two modes for test discovery, *strict* and *auto*.
20+
21+
22+
Strict mode
23+
-----------
24+
25+
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.
26+
27+
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.
28+
29+
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.
30+
31+
Auto mode
32+
---------
33+
34+
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``.
35+
36+
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.
37+
38+
If you intend to support multiple asynchronous programming libraries, e.g. *asyncio* and *trio*, strict mode will be the preferred option.

Diff for: docs/source/conf.py

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Configuration file for the Sphinx documentation builder.
2+
#
3+
# For the full list of built-in configuration values, see the documentation:
4+
# https://www.sphinx-doc.org/en/master/usage/configuration.html
5+
6+
# -- Project information -----------------------------------------------------
7+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
8+
9+
project = "pytest-asyncio"
10+
copyright = "2022, pytest-asyncio contributors"
11+
author = "Tin Tvrtković"
12+
release = "v0.20.1"
13+
14+
# -- General configuration ---------------------------------------------------
15+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
16+
17+
extensions = []
18+
19+
templates_path = ["_templates"]
20+
exclude_patterns = []
21+
22+
23+
# -- Options for HTML output -------------------------------------------------
24+
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
25+
26+
html_theme = "sphinx_rtd_theme"
27+
html_static_path = ["_static"]

Diff for: docs/source/index.rst

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
==========================
2+
Welcome to pytest-asyncio!
3+
==========================
4+
5+
.. toctree::
6+
:maxdepth: 1
7+
:hidden:
8+
9+
concepts
10+
reference
11+
support
12+
13+
pytest-asyncio is a `pytest <https://docs.pytest.org/en/latest/contents.html>`_ plugin. It facilitates testing of code that uses the `asyncio <https://docs.python.org/3/library/asyncio.html>`_ library.
14+
15+
Specifically, pytest-asyncio provides support for coroutines as test functions. This allows users to *await* code inside their tests. For example, the following code is executed as a test item by pytest:
16+
17+
.. code-block:: python
18+
19+
@pytest.mark.asyncio
20+
async def test_some_asyncio_code():
21+
res = await library.do_something()
22+
assert b"expected result" == res
23+
24+
25+
Note that test classes subclassing the standard `unittest <https://docs.python.org/3/library/unittest.html>`__ library are not supported. Users
26+
are advised to use `unittest.IsolatedAsyncioTestCase <https://docs.python.org/3/library/unittest.html#unittest.IsolatedAsyncioTestCase>`__
27+
or an async framework such as `asynctest <https://asynctest.readthedocs.io/en/latest>`__.
28+
29+
30+
pytest-asyncio is available under the `Apache License 2.0 <https://github.com/pytest-dev/pytest-asyncio/blob/master/LICENSE>`_.

0 commit comments

Comments
 (0)