tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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.