Skip to content

Commit ccd5ec2

Browse files
committed
Support Trio testing with Hypothesis
1 parent 8a52d49 commit ccd5ec2

File tree

5 files changed

+50
-5
lines changed

5 files changed

+50
-5
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ htmlcov/
4040
.cache
4141
nosetests.xml
4242
coverage.xml
43+
.hypothesis/
44+
.pytest_cache/
4345

4446
# Translations
4547
*.mo

newsfragments/42.feature.rst

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pytest-trio now integrates with `Hypothesis <https://hypothesis.readthedocs.io>`_
2+
to support ``@given`` on async tests using Trio.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import pytest
2+
from hypothesis import given, strategies as st
3+
4+
5+
@given(st.integers())
6+
@pytest.mark.trio
7+
async def test_mark_inner(n):
8+
assert isinstance(n, int)
9+
10+
11+
@pytest.mark.trio
12+
@given(st.integers())
13+
async def test_mark_outer(n):
14+
assert isinstance(n, int)
15+
16+
17+
@pytest.mark.parametrize('y', [1, 2])
18+
@given(x=st.none())
19+
@pytest.mark.trio
20+
async def test_mark_and_parametrize(x, y):
21+
assert x is None
22+
assert y in (1, 2)

pytest_trio/plugin.py

+23-5
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,18 @@ def pytest_configure(config):
2525
)
2626

2727

28-
def _trio_test_runner_factory(item):
29-
testfunc = item.function
28+
def _trio_test_runner_factory(item, testfunc=None):
29+
testfunc = testfunc or item.function
30+
31+
if getattr(testfunc, '_trio_test_runner_wrapped', False):
32+
# We have already wrapped this, perhaps because we combined Hypothesis
33+
# with pytest.mark.parametrize
34+
return testfunc
35+
36+
if not iscoroutinefunction(testfunc):
37+
pytest.fail(
38+
'test function `%r` is marked trio but is not async' % item
39+
)
3040

3141
@trio_test
3242
async def _bootstrap_fixture_and_run_test(**kwargs):
@@ -58,6 +68,7 @@ async def _bootstrap_fixture_and_run_test(**kwargs):
5868
if user_exc:
5969
raise user_exc
6070

71+
_bootstrap_fixture_and_run_test._trio_test_runner_wrapped = True
6172
return _bootstrap_fixture_and_run_test
6273

6374

@@ -215,11 +226,18 @@ def _install_async_fixture_if_needed(fixturedef, request):
215226
@pytest.hookimpl(hookwrapper=True)
216227
def pytest_runtest_call(item):
217228
if 'trio' in item.keywords:
218-
if not iscoroutinefunction(item.obj):
229+
if hasattr(item.obj, 'hypothesis'):
230+
# If it's a Hypothesis test, we go in a layer.
231+
item.obj.hypothesis.inner_test = _trio_test_runner_factory(
232+
item, item.obj.hypothesis.inner_test
233+
)
234+
elif getattr(item.obj, 'is_hypothesis_test', False):
219235
pytest.fail(
220-
'test function `%r` is marked trio but is not async' % item
236+
'test function `%r` is using Hypothesis, but pytest-trio '
237+
'only works with Hypothesis 3.64.0 or later.' % item
221238
)
222-
item.obj = _trio_test_runner_factory(item)
239+
else:
240+
item.obj = _trio_test_runner_factory(item)
223241

224242
yield
225243

test-requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pytest
22
pytest-cov
3+
hypothesis>=3.64

0 commit comments

Comments
 (0)