Skip to content

Commit ab0466b

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 ab0466b

File tree

1 file changed

+18
-29
lines changed

1 file changed

+18
-29
lines changed

pytest_asyncio/plugin.py

+18-29
Original file line numberDiff line numberDiff line change
@@ -138,40 +138,33 @@ 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):
150-
event_loop = pyfuncitem.funcargs[fixture_name]
151-
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
148+
if marker_name in pyfuncitem.keywords:
149+
if getattr(pyfuncitem.obj, 'is_hypothesis_test', False):
150+
pyfuncitem.obj.hypothesis.inner_test = wrap_in_sync(
151+
pyfuncitem.obj.hypothesis.inner_test
152+
)
153+
else:
154+
pyfuncitem.obj = wrap_in_sync(pyfuncitem.obj)
155+
yield
160156

161157

162158
def wrap_in_sync(func):
163-
"""Return a sync wrapper around an async function."""
159+
"""Return a sync wrapper around an async function executing it in the
160+
current event loop."""
164161

165162
@functools.wraps(func)
166163
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()
164+
coro = func(**kwargs)
165+
if coro is not None:
166+
future = asyncio.ensure_future(coro)
167+
asyncio.get_event_loop().run_until_complete(future)
175168

176169
return inner
177170

@@ -181,13 +174,9 @@ def pytest_runtest_setup(item):
181174
if marker in item.keywords and fixture not in item.fixturenames:
182175
# inject an event loop fixture for all async tests
183176
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):
177+
if item.get_closest_marker("asyncio") is not None \
178+
and not getattr(item.obj, 'hypothesis', False) \
179+
and getattr(item.obj, 'is_hypothesis_test', False):
191180
pytest.fail(
192181
'test function `%r` is using Hypothesis, but pytest-asyncio '
193182
'only works with Hypothesis 3.64.0 or later.' % item

0 commit comments

Comments
 (0)