Skip to content

Commit 33d4c96

Browse files
authored
Merge pull request #4830 from nicoddemus/warn-on-coroutine
Emit a warning when a coroutine test function is encountered
2 parents 5f52d5e + 40072b9 commit 33d4c96

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

changelog/2224.feature.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``async`` test functions are skipped and a warning is emitted when a suitable
2+
async plugin is not installed (such as ``pytest-asyncio`` or ``pytest-trio``).
3+
4+
Previously ``async`` functions would not execute at all but still be marked as "passed".

src/_pytest/python.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from _pytest.mark.structures import get_unpacked_marks
4444
from _pytest.mark.structures import normalize_mark_list
4545
from _pytest.outcomes import fail
46+
from _pytest.outcomes import skip
4647
from _pytest.pathlib import parts
4748
from _pytest.warning_types import PytestWarning
4849

@@ -156,6 +157,15 @@ def pytest_configure(config):
156157
@hookimpl(trylast=True)
157158
def pytest_pyfunc_call(pyfuncitem):
158159
testfunction = pyfuncitem.obj
160+
iscoroutinefunction = getattr(inspect, "iscoroutinefunction", None)
161+
if iscoroutinefunction is not None and iscoroutinefunction(testfunction):
162+
msg = "Coroutine functions are not natively supported and have been skipped.\n"
163+
msg += "You need to install a suitable plugin for your async framework, for example:\n"
164+
msg += " - pytest-asyncio\n"
165+
msg += " - pytest-trio\n"
166+
msg += " - pytest-tornasync"
167+
warnings.warn(PytestWarning(msg.format(pyfuncitem.nodeid)))
168+
skip(msg="coroutine function and no async plugin installed (see warnings)")
159169
funcargs = pyfuncitem.funcargs
160170
testargs = {arg: funcargs[arg] for arg in pyfuncitem._fixtureinfo.argnames}
161171
testfunction(**testargs)

testing/acceptance_test.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,3 +1179,31 @@ def test_fixture_mock_integration(testdir):
11791179
def test_usage_error_code(testdir):
11801180
result = testdir.runpytest("-unknown-option-")
11811181
assert result.ret == EXIT_USAGEERROR
1182+
1183+
1184+
@pytest.mark.skipif(
1185+
sys.version_info[:2] < (3, 5), reason="async def syntax python 3.5+ only"
1186+
)
1187+
@pytest.mark.filterwarnings("default")
1188+
def test_warn_on_async_function(testdir):
1189+
testdir.makepyfile(
1190+
test_async="""
1191+
async def test_1():
1192+
pass
1193+
async def test_2():
1194+
pass
1195+
"""
1196+
)
1197+
result = testdir.runpytest()
1198+
result.stdout.fnmatch_lines(
1199+
[
1200+
"test_async.py::test_1",
1201+
"test_async.py::test_2",
1202+
"*Coroutine functions are not natively supported*",
1203+
"*2 skipped, 2 warnings in*",
1204+
]
1205+
)
1206+
# ensure our warning message appears only once
1207+
assert (
1208+
result.stdout.str().count("Coroutine functions are not natively supported") == 1
1209+
)

0 commit comments

Comments
 (0)