Skip to content

Commit 62ff26f

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 <m.seifert@digitalernachschub.de>
1 parent 54d212b commit 62ff26f

File tree

9 files changed

+138
-2
lines changed

9 files changed

+138
-2
lines changed

Diff for: docs/source/how-to-guides/index.rst

+1
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.

Diff for: docs/source/how-to-guides/test_item_is_async.rst

+7
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
+7
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

Diff for: docs/source/reference/changelog.rst

+1
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)

Diff for: docs/source/reference/functions.rst

+9
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.

Diff for: docs/source/reference/index.rst

+1
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

Diff for: pytest_asyncio/__init__.py

+2-2
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")

Diff for: pytest_asyncio/plugin.py

+5
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:

Diff for: tests/test_is_async_test.py

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

0 commit comments

Comments
 (0)