Skip to content

Commit 69a1213

Browse files
committed
[feat] Added new function "is_async_test" which returns whether a pytest Item is an async test managed by pytest-asyncio.
Signed-off-by: Michael Seifert <[email protected]>
1 parent 54d212b commit 69a1213

File tree

9 files changed

+133
-2
lines changed

9 files changed

+133
-2
lines changed

docs/source/how-to-guides/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,6 @@ How-To Guides
77

88
multiple_loops
99
uvloop
10+
test_item_is_async
1011

1112
This section of the documentation provides code snippets and recipes to accomplish specific tasks with pytest-asyncio.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
=======================================
2+
How to tell if a test function is async
3+
=======================================
4+
Use ``pytest_asyncio.is_async_item`` to determine if a test item is asynchronous and managed by pytest-asyncio.
5+
6+
.. include:: test_item_is_async_example.py
7+
:code: python
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from pytest_asyncio import is_async_test
2+
3+
4+
def pytest_collection_modifyitems(items):
5+
for item in items:
6+
if is_async_test(item):
7+
pass

docs/source/reference/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Changes are non-breaking, unless you upgrade from v0.22.
99

1010
- BREAKING: The *asyncio_event_loop* mark has been removed. Event loops with class, module, package, and session scopes can be requested via the *scope* keyword argument to the _asyncio_ mark.
1111
- Introduces the *event_loop_policy* fixture which allows testing with non-default or multiple event loops `#662 <https://github.com/pytest-dev/pytest-asyncio/pull/662>`_
12+
- Introduces ``pytest_asyncio.is_async_test`` which returns whether a test item is managed by pytest-asyncio `#376 <https://github.com/pytest-dev/pytest-asyncio/issues/376>`_
1213
- Removes pytest-trio from the test dependencies `#620 <https://github.com/pytest-dev/pytest-asyncio/pull/620>`_
1314

1415
0.22.0 (2023-10-31)

docs/source/reference/functions.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
=========
2+
Functions
3+
=========
4+
5+
is_async_test
6+
=============
7+
Returns whether a specific pytest Item is an asynchronous test managed by pytest-asyncio.
8+
9+
This function is intended to be used in pytest hooks or by plugins that depend on pytest-asyncio.

docs/source/reference/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Reference
77

88
configuration
99
fixtures/index
10+
functions
1011
markers/index
1112
decorators/index
1213
changelog

pytest_asyncio/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""The main point for importing pytest-asyncio items."""
22
from ._version import version as __version__ # noqa
3-
from .plugin import fixture
3+
from .plugin import fixture, is_async_test
44

5-
__all__ = ("fixture",)
5+
__all__ = ("fixture", "is_async_test")

pytest_asyncio/plugin.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -963,6 +963,11 @@ def event_loop_policy() -> AbstractEventLoopPolicy:
963963
return asyncio.get_event_loop_policy()
964964

965965

966+
def is_async_test(item: Item) -> bool:
967+
"""Returns whether a test item is a pytest-asyncio test"""
968+
return isinstance(item, PytestAsyncioFunction)
969+
970+
966971
def _unused_port(socket_type: int) -> int:
967972
"""Find an unused localhost port from 1024-65535 and return it."""
968973
with contextlib.closing(socket.socket(type=socket_type)) as sock:

tests/test_is_async_test.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
from textwrap import dedent
2+
3+
from pytest import Pytester
4+
5+
6+
def test_returns_false_for_sync_item(pytester: Pytester):
7+
pytester.makepyfile(
8+
dedent(
9+
"""\
10+
import pytest
11+
import pytest_asyncio
12+
13+
def test_sync():
14+
pass
15+
16+
def pytest_collection_modifyitems(items):
17+
async_tests = [
18+
item
19+
for item in items
20+
if pytest_asyncio.is_async_test(item)
21+
]
22+
assert len(async_tests) == 0
23+
"""
24+
)
25+
)
26+
result = pytester.runpytest("--asyncio-mode=strict")
27+
result.assert_outcomes(passed=1)
28+
29+
30+
def test_returns_true_for_marked_coroutine_item_in_strict_mode(pytester: Pytester):
31+
pytester.makepyfile(
32+
dedent(
33+
"""\
34+
import pytest
35+
import pytest_asyncio
36+
37+
@pytest.mark.asyncio
38+
async def test_coro():
39+
pass
40+
41+
def pytest_collection_modifyitems(items):
42+
async_tests = [
43+
item
44+
for item in items
45+
if pytest_asyncio.is_async_test(item)
46+
]
47+
assert len(async_tests) == 1
48+
"""
49+
)
50+
)
51+
result = pytester.runpytest("--asyncio-mode=strict")
52+
result.assert_outcomes(passed=1)
53+
54+
55+
def test_returns_false_for_unmarked_coroutine_item_in_strict_mode(pytester: Pytester):
56+
pytester.makepyfile(
57+
dedent(
58+
"""\
59+
import pytest
60+
import pytest_asyncio
61+
62+
async def test_coro():
63+
pass
64+
65+
def pytest_collection_modifyitems(items):
66+
async_tests = [
67+
item
68+
for item in items
69+
if pytest_asyncio.is_async_test(item)
70+
]
71+
assert len(async_tests) == 0
72+
"""
73+
)
74+
)
75+
result = pytester.runpytest("--asyncio-mode=strict")
76+
result.assert_outcomes(skipped=1)
77+
78+
79+
def test_returns_true_for_unmarked_coroutine_item_in_auto_mode(pytester: Pytester):
80+
pytester.makepyfile(
81+
dedent(
82+
"""\
83+
import pytest
84+
import pytest_asyncio
85+
86+
async def test_coro():
87+
pass
88+
89+
def pytest_collection_modifyitems(items):
90+
async_tests = [
91+
item
92+
for item in items
93+
if pytest_asyncio.is_async_test(item)
94+
]
95+
assert len(async_tests) == 1
96+
"""
97+
)
98+
)
99+
result = pytester.runpytest("--asyncio-mode=auto")
100+
result.assert_outcomes(passed=1)

0 commit comments

Comments
 (0)