diff --git a/_pytest/compat.py b/_pytest/compat.py index d278b89cd44..a5d2e2be1f9 100644 --- a/_pytest/compat.py +++ b/_pytest/compat.py @@ -227,6 +227,13 @@ def _is_unittest_unexpected_success_a_failure(): return sys.version_info >= (3, 4) +if hasattr(inspect, 'isawaitable'): + isawaitable = inspect.isawaitable +else: + def isawaitable(f): + return False + + if _PY3: def safe_str(v): """returns v as string""" diff --git a/_pytest/python.py b/_pytest/python.py index e46f2f1bcfb..13853114ef8 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -19,7 +19,7 @@ isclass, isfunction, is_generator, _escape_strings, REGEX_TYPE, STRING_TYPES, NoneType, NOTSET, get_real_func, getfslineno, safe_getattr, - getlocation, enum, + getlocation, enum, isawaitable, ) cutdir1 = py.path.local(pluggy.__file__.rstrip("oc")) @@ -151,7 +151,11 @@ def pytest_pyfunc_call(pyfuncitem): testargs = {} for arg in pyfuncitem._fixtureinfo.argnames: testargs[arg] = funcargs[arg] - testfunction(**testargs) + testreturn = testfunction(**testargs) + if isawaitable(testreturn): + import asyncio + loop = asyncio.get_event_loop() + loop.run_until_complete(testreturn) return True def pytest_collect_file(path, parent): diff --git a/testing/test_async.py b/testing/test_async.py new file mode 100644 index 00000000000..8693e7a2f4d --- /dev/null +++ b/testing/test_async.py @@ -0,0 +1,14 @@ +import sys + +import pytest + + +@pytest.mark.skipif(sys.version_info < (3, 5), reason='async syntax available in Python 3.5+') +def test_async_function(testdir): + testdir.makepyfile(""" + async def test_async_function_py35(): + assert False + """) + # avoid importing asyncio into pytest's own process, which in turn imports logging (#8) + result = testdir.runpytest_subprocess() + result.stdout.fnmatch_lines(['*1 failed*'])