README.rst (9140B)
1 pytest-asyncio: pytest support for asyncio 2 ========================================== 3 4 .. image:: https://img.shields.io/pypi/v/pytest-asyncio.svg 5 :target: https://pypi.python.org/pypi/pytest-asyncio 6 .. image:: https://github.com/pytest-dev/pytest-asyncio/workflows/CI/badge.svg 7 :target: https://github.com/pytest-dev/pytest-asyncio/actions?workflow=CI 8 .. image:: https://codecov.io/gh/pytest-dev/pytest-asyncio/branch/master/graph/badge.svg 9 :target: https://codecov.io/gh/pytest-dev/pytest-asyncio 10 .. image:: https://img.shields.io/pypi/pyversions/pytest-asyncio.svg 11 :target: https://github.com/pytest-dev/pytest-asyncio 12 :alt: Supported Python versions 13 .. image:: https://img.shields.io/badge/code%20style-black-000000.svg 14 :target: https://github.com/ambv/black 15 16 pytest-asyncio is an Apache2 licensed library, written in Python, for testing 17 asyncio code with pytest. 18 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. 22 23 .. code-block:: python 24 25 @pytest.mark.asyncio 26 async def test_some_asyncio_code(): 27 res = await library.do_something() 28 assert b"expected result" == res 29 30 pytest-asyncio has been strongly influenced by pytest-tornado_. 31 32 .. _pytest-tornado: https://github.com/eugeniy/pytest-tornado 33 34 Features 35 -------- 36 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``. 45 46 Installation 47 ------------ 48 49 To install pytest-asyncio, simply: 50 51 .. code-block:: bash 52 53 $ pip install pytest-asyncio 54 55 This is enough for pytest to pick up pytest-asyncio. 56 57 Modes 58 ----- 59 60 Starting from ``pytest-asyncio>=0.17``, three modes are provided: *auto*, *strict* and 61 *legacy*. Starting from ``pytest-asyncio>=0.19`` the *strict* mode is the default. 62 63 The mode can be set by ``asyncio_mode`` configuration option in `configuration file 64 <https://docs.pytest.org/en/latest/reference/customize.html>`_: 65 66 .. code-block:: ini 67 68 # pytest.ini 69 [pytest] 70 asyncio_mode = auto 71 72 The value can be overridden by command-line option for ``pytest`` invocation: 73 74 .. code-block:: bash 75 76 $ pytest tests --asyncio-mode=strict 77 78 Auto mode 79 ~~~~~~~~~ 80 81 When the mode is auto, all discovered *async* tests are considered *asyncio-driven* even 82 if they have no ``@pytest.mark.asyncio`` marker. 83 84 All async fixtures are considered *asyncio-driven* as well, even if they are decorated 85 with a regular ``@pytest.fixture`` decorator instead of dedicated 86 ``@pytest_asyncio.fixture`` counterpart. 87 88 *asyncio-driven* means that tests and fixtures are executed by ``pytest-asyncio`` 89 plugin. 90 91 This mode requires the simplest tests and fixtures configuration and is 92 recommended for default usage *unless* the same project and its test suite should 93 execute tests from different async frameworks, e.g. ``asyncio`` and ``trio``. In this 94 case, auto-handling can break tests designed for other framework; please use *strict* 95 mode instead. 96 97 Strict mode 98 ~~~~~~~~~~~ 99 100 Strict mode enforces ``@pytest.mark.asyncio`` and ``@pytest_asyncio.fixture`` usage. 101 Without these markers, tests and fixtures are not considered as *asyncio-driven*, other 102 pytest plugin can handle them. 103 104 Please use this mode if multiple async frameworks should be combined in the same test 105 suite. 106 107 This mode is used by default for the sake of project inter-compatibility. 108 109 110 Legacy mode 111 ~~~~~~~~~~~ 112 113 This mode follows rules used by ``pytest-asyncio<0.17``: tests are not auto-marked but 114 fixtures are. 115 116 Deprecation warnings are emitted with suggestion to either switching to ``auto`` mode 117 or using ``strict`` mode with ``@pytest_asyncio.fixture`` decorators. 118 119 The default was changed to ``strict`` in ``pytest-asyncio>=0.19``. 120 121 122 Fixtures 123 -------- 124 125 ``event_loop`` 126 ~~~~~~~~~~~~~~ 127 Creates a new asyncio event loop based on the current event loop policy. The new loop 128 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>`__. 129 The event loop is closed when the fixture scope ends. The fixture scope defaults 130 to ``function`` scope. 131 132 Note that just using the ``event_loop`` fixture won't make your test function 133 a coroutine. You'll need to interact with the event loop directly, using methods 134 like ``event_loop.run_until_complete``. See the ``pytest.mark.asyncio`` marker 135 for treating test functions like coroutines. 136 137 .. code-block:: python 138 139 def test_http_client(event_loop): 140 url = "http://httpbin.org/get" 141 resp = event_loop.run_until_complete(http_client(url)) 142 assert b"HTTP/1.1 200 OK" in resp 143 144 The ``event_loop`` fixture can be overridden in any of the standard pytest locations, 145 e.g. directly in the test file, or in ``conftest.py``. This allows redefining the 146 fixture scope, for example: 147 148 .. code-block:: python 149 150 @pytest.fixture(scope="session") 151 def event_loop(): 152 policy = asyncio.get_event_loop_policy() 153 loop = policy.new_event_loop() 154 yield loop 155 loop.close() 156 157 If you need to change the type of the event loop, prefer setting a custom event loop policy over redefining the ``event_loop`` fixture. 158 159 If the ``pytest.mark.asyncio`` marker is applied to a test function, the ``event_loop`` 160 fixture will be requested automatically by the test function. 161 162 ``unused_tcp_port`` 163 ~~~~~~~~~~~~~~~~~~~ 164 Finds and yields a single unused TCP port on the localhost interface. Useful for 165 binding temporary test servers. 166 167 ``unused_tcp_port_factory`` 168 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 169 A callable which returns a different unused TCP port each invocation. Useful 170 when several unused TCP ports are required in a test. 171 172 .. code-block:: python 173 174 def a_test(unused_tcp_port_factory): 175 port1, port2 = unused_tcp_port_factory(), unused_tcp_port_factory() 176 ... 177 178 ``unused_udp_port`` and ``unused_udp_port_factory`` 179 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 180 Work just like their TCP counterparts but return unused UDP ports. 181 182 183 Async fixtures 184 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 185 Asynchronous fixtures are defined just like ordinary pytest fixtures, except they should be decorated with ``@pytest_asyncio.fixture``. 186 187 .. code-block:: python3 188 189 import pytest_asyncio 190 191 192 @pytest_asyncio.fixture 193 async def async_gen_fixture(): 194 await asyncio.sleep(0.1) 195 yield "a value" 196 197 198 @pytest_asyncio.fixture(scope="module") 199 async def async_fixture(): 200 return await asyncio.sleep(0.1) 201 202 All scopes are supported, but if you use a non-function scope you will need 203 to redefine the ``event_loop`` fixture to have the same or broader scope. 204 Async fixtures need the event loop, and so must have the same or narrower scope 205 than the ``event_loop`` fixture. 206 207 *auto* and *legacy* mode automatically converts async fixtures declared with the 208 standard ``@pytest.fixture`` decorator to *asyncio-driven* versions. 209 210 211 Markers 212 ------- 213 214 ``pytest.mark.asyncio`` 215 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 216 Mark your test coroutine with this marker and pytest will execute it as an 217 asyncio task using the event loop provided by the ``event_loop`` fixture. See 218 the introductory section for an example. 219 220 The event loop used can be overridden by overriding the ``event_loop`` fixture 221 (see above). 222 223 In order to make your test code a little more concise, the pytest |pytestmark|_ 224 feature can be used to mark entire modules or classes with this marker. 225 Only test coroutines will be affected (by default, coroutines prefixed by 226 ``test_``), so, for example, fixtures are safe to define. 227 228 .. code-block:: python 229 230 import asyncio 231 232 import pytest 233 234 # All test coroutines will be treated as marked. 235 pytestmark = pytest.mark.asyncio 236 237 238 async def test_example(event_loop): 239 """No marker!""" 240 await asyncio.sleep(0, loop=event_loop) 241 242 In *auto* mode, the ``pytest.mark.asyncio`` marker can be omitted, the marker is added 243 automatically to *async* test functions. 244 245 246 .. |pytestmark| replace:: ``pytestmark`` 247 .. _pytestmark: http://doc.pytest.org/en/latest/example/markers.html#marking-whole-classes-or-modules 248 249 Note about unittest 250 ------------------- 251 252 Test classes subclassing the standard `unittest <https://docs.python.org/3/library/unittest.html>`__ library are not supported, users 253 are recommended to use `unittest.IsolatedAsyncioTestCase <https://docs.python.org/3/library/unittest.html#unittest.IsolatedAsyncioTestCase>`__ 254 or an async framework such as `asynctest <https://asynctest.readthedocs.io/en/latest>`__. 255 256 Contributing 257 ------------ 258 Contributions are very welcome. Tests can be run with ``tox``, please ensure 259 the coverage at least stays the same before you submit a pull request.