You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
pytest-asyncio provides an asyncio event loop via the event_loop fixture. The fixture is function-scoped by default. This is useful for unit testing as it ensures a high level of isolation between test cases. However, as soon as users want to write larger tests that span multiple test cases the scope of the event_loop fixture needs to be extended.
Extending the scope of the event_loop fixture is currently achieved by reimplementing the fixture with an appropriate scope. This approach leads to code duplication, because users are forced to implement the fixture body over and over again. Users are also known to modify the fixture implementation and extend it with custom setup or teardown code.
Several problems arise from this: For one, changes to the fixture implementation in pytest-asyncio would require all users to change their fixture implementations accordingly. For another, requiring users to implement their own event_loop fixture somewhat defeats the purpose of pytest-asyncio in the first place.
Proposed solution
Pytest nodes are discovered by a hierarchy of collectors. Pytest marks can be located at different levels of this hierarchy (see Marking whole classes or modules).
The proposed solution is to derive the scope of the asyncio event loop from the location of the asyncio mark. Consider the following examples.
Discussed in #587
Originally posted by seifertm July 18, 2023
Motivation
pytest-asyncio provides an asyncio event loop via the event_loop fixture. The fixture is function-scoped by default. This is useful for unit testing as it ensures a high level of isolation between test cases. However, as soon as users want to write larger tests that span multiple test cases the scope of the event_loop fixture needs to be extended.
Extending the scope of the event_loop fixture is currently achieved by reimplementing the fixture with an appropriate scope. This approach leads to code duplication, because users are forced to implement the fixture body over and over again. Users are also known to modify the fixture implementation and extend it with custom setup or teardown code.
Several problems arise from this: For one, changes to the fixture implementation in pytest-asyncio would require all users to change their fixture implementations accordingly. For another, requiring users to implement their own event_loop fixture somewhat defeats the purpose of pytest-asyncio in the first place.
Proposed solution
Pytest nodes are discovered by a hierarchy of collectors. Pytest marks can be located at different levels of this hierarchy (see Marking whole classes or modules).
The proposed solution is to derive the scope of the asyncio event loop from the location of the
asyncio
mark. Consider the following examples.Strict mode
Test functions
Each function test_a and test_b have their own asyncio mark. Therefore, the event loop scope will be limited to each test function.
Test classes
When using test classes the scope of the event loop can be per-class or per-function, depending on the location of
the
asyncio
mark.The functions test_a and test_b each run in their own loop, because the asyncio marker is directly attached to them.
The functions test_a and test_b run in a common loop, because the asyncio marker is attached to the class.
Module-scoped loops
If the entire module has the
asyncio
mark all tests are run in a module-scoped event loop.Auto mode
Function scope
Class scope
Module scope
Session scope
Considered alternatives
Dynamic fixture scopes
pytest-dev/pytest#6101
Introducing dynamic fixture scope in pytest is more effort compared to the proposed solution as it introduces new features to pytest.
The text was updated successfully, but these errors were encountered: