Skip to content

Commit c57d535

Browse files
committed
Execute 'async def' test functions
pytest didn't use the result of test functions but `async def` functions return an awaitable object. Though `async def` functions were just passed like they don't have any problem, their codes actually didn't run. For users, it was really hard to detect the tests really were run or not. This patch makes to check the result of test functions and if it is an awaitable object then actually run the functions to ensure its code is run.
1 parent 64cb67b commit c57d535

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

_pytest/compat.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,13 @@ def _is_unittest_unexpected_success_a_failure():
227227
return sys.version_info >= (3, 4)
228228

229229

230+
if hasattr(inspect, 'isawaitable'):
231+
isawaitable = inspect.isawaitable
232+
else:
233+
def isawaitable(f):
234+
return False
235+
236+
230237
if _PY3:
231238
def safe_str(v):
232239
"""returns v as string"""

_pytest/python.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
isclass, isfunction, is_generator, _escape_strings,
2020
REGEX_TYPE, STRING_TYPES, NoneType, NOTSET,
2121
get_real_func, getfslineno, safe_getattr,
22-
getlocation, enum,
22+
getlocation, enum, isawaitable,
2323
)
2424

2525
cutdir1 = py.path.local(pluggy.__file__.rstrip("oc"))
@@ -151,7 +151,11 @@ def pytest_pyfunc_call(pyfuncitem):
151151
testargs = {}
152152
for arg in pyfuncitem._fixtureinfo.argnames:
153153
testargs[arg] = funcargs[arg]
154-
testfunction(**testargs)
154+
testreturn = testfunction(**testargs)
155+
if isawaitable(testreturn):
156+
import asyncio
157+
loop = asyncio.get_event_loop()
158+
loop.run_until_complete(testreturn)
155159
return True
156160

157161
def pytest_collect_file(path, parent):

testing/test_async.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import sys
2+
3+
import pytest
4+
5+
6+
@pytest.mark.skipif(sys.version_info < (3, 5), reason='async syntax available in Python 3.5+')
7+
def test_async_function(testdir):
8+
testdir.makepyfile("""
9+
async def test_async_function_py35():
10+
assert False
11+
""")
12+
# avoid importing asyncio into pytest's own process, which in turn imports logging (#8)
13+
result = testdir.runpytest_subprocess()
14+
result.stdout.fnmatch_lines(['*1 failed*'])

0 commit comments

Comments
 (0)