Skip to content

Commit dee505e

Browse files
committed
Sync wrapper for hypothesis tests uses the event loop provided by pytest-asyncio instead of creating a new loop.
1 parent f35d06b commit dee505e

File tree

1 file changed

+19
-29
lines changed

1 file changed

+19
-29
lines changed

pytest_asyncio/plugin.py

+19-29
Original file line numberDiff line numberDiff line change
@@ -138,40 +138,34 @@ async def setup():
138138
fixturedef.addfinalizer(lambda: policy.set_event_loop(old_loop))
139139

140140

141-
@pytest.mark.tryfirst
141+
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
142142
def pytest_pyfunc_call(pyfuncitem):
143143
"""
144144
Run asyncio marked test functions in an event loop instead of a normal
145145
function call.
146146
"""
147147
for marker_name, fixture_name in _markers_2_fixtures.items():
148-
if marker_name in pyfuncitem.keywords \
149-
and not getattr(pyfuncitem.obj, 'is_hypothesis_test', False):
148+
if marker_name in pyfuncitem.keywords:
150149
event_loop = pyfuncitem.funcargs[fixture_name]
150+
if getattr(pyfuncitem.obj, 'is_hypothesis_test', False):
151+
pyfuncitem.obj.hypothesis.inner_test = wrap_in_sync(
152+
pyfuncitem.obj.hypothesis.inner_test, event_loop
153+
)
154+
else:
155+
pyfuncitem.obj = wrap_in_sync(pyfuncitem.obj, event_loop)
156+
yield
151157

152-
funcargs = pyfuncitem.funcargs
153-
testargs = {arg: funcargs[arg]
154-
for arg in pyfuncitem._fixtureinfo.argnames}
155-
156-
event_loop.run_until_complete(
157-
asyncio.ensure_future(
158-
pyfuncitem.obj(**testargs), loop=event_loop))
159-
return True
160158

161-
162-
def wrap_in_sync(func):
163-
"""Return a sync wrapper around an async function."""
159+
def wrap_in_sync(func, loop):
160+
"""Return a sync wrapper around an async function executing it in the
161+
specified event loop."""
164162

165163
@functools.wraps(func)
166164
def inner(**kwargs):
167-
loop = asyncio.get_event_loop_policy().new_event_loop()
168-
try:
169-
coro = func(**kwargs)
170-
if coro is not None:
171-
future = asyncio.ensure_future(coro, loop=loop)
172-
loop.run_until_complete(future)
173-
finally:
174-
loop.close()
165+
coro = func(**kwargs)
166+
if coro is not None:
167+
future = asyncio.ensure_future(coro, loop=loop)
168+
loop.run_until_complete(future)
175169

176170
return inner
177171

@@ -181,13 +175,9 @@ def pytest_runtest_setup(item):
181175
if marker in item.keywords and fixture not in item.fixturenames:
182176
# inject an event loop fixture for all async tests
183177
item.fixturenames.append(fixture)
184-
if item.get_closest_marker("asyncio") is not None:
185-
if hasattr(item.obj, 'hypothesis'):
186-
# If it's a Hypothesis test, we insert the wrap_in_sync decorator
187-
item.obj.hypothesis.inner_test = wrap_in_sync(
188-
item.obj.hypothesis.inner_test
189-
)
190-
elif getattr(item.obj, 'is_hypothesis_test', False):
178+
if item.get_closest_marker("asyncio") is not None \
179+
and not getattr(item.obj, 'hypothesis', False) \
180+
and getattr(item.obj, 'is_hypothesis_test', False):
191181
pytest.fail(
192182
'test function `%r` is using Hypothesis, but pytest-asyncio '
193183
'only works with Hypothesis 3.64.0 or later.' % item

0 commit comments

Comments
 (0)