Skip to content

Commit 61a27c2

Browse files
authored
Merge pull request #152 from pytest-dev/hypothesis
support hypothesis
2 parents 8dc50e9 + 6f7c883 commit 61a27c2

File tree

3 files changed

+126
-8
lines changed

3 files changed

+126
-8
lines changed

pytest_twisted.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -375,27 +375,51 @@ def pytest_pyfunc_call(pyfuncitem):
375375
# TODO: only handle 'our' tests? what is the point of handling others?
376376
# well, because our interface allowed people to return deferreds
377377
# from arbitrary tests so we kinda have to keep this up for now
378-
_run_inline_callbacks(_async_pytest_pyfunc_call, pyfuncitem)
379-
return not None
378+
maybe_hypothesis = getattr(pyfuncitem.obj, "hypothesis", None)
379+
if maybe_hypothesis is None:
380+
_run_inline_callbacks(
381+
_async_pytest_pyfunc_call,
382+
pyfuncitem,
383+
pyfuncitem.obj,
384+
{}
385+
)
386+
result = not None
387+
else:
388+
hypothesis = maybe_hypothesis
389+
f = hypothesis.inner_test
390+
391+
def inner_test(**kwargs):
392+
return _run_inline_callbacks(
393+
_async_pytest_pyfunc_call,
394+
pyfuncitem,
395+
f,
396+
kwargs,
397+
)
398+
399+
pyfuncitem.obj.hypothesis.inner_test = inner_test
400+
result = None
401+
402+
return result
380403

381404

382405
@defer.inlineCallbacks
383-
def _async_pytest_pyfunc_call(pyfuncitem):
406+
def _async_pytest_pyfunc_call(pyfuncitem, f, kwargs):
384407
"""Run test function."""
385-
kwargs = {
408+
fixture_kwargs = {
386409
name: value
387410
for name, value in pyfuncitem.funcargs.items()
388411
if name in pyfuncitem._fixtureinfo.argnames
389412
}
413+
kwargs.update(fixture_kwargs)
390414

391-
maybe_mark = _get_mark(pyfuncitem.obj)
415+
maybe_mark = _get_mark(f)
392416
if maybe_mark == 'async_test':
393-
result = yield defer.ensureDeferred(pyfuncitem.obj(**kwargs))
417+
result = yield defer.ensureDeferred(f(**kwargs))
394418
elif maybe_mark == 'inline_callbacks_test':
395-
result = yield pyfuncitem.obj(**kwargs)
419+
result = yield f(**kwargs)
396420
else:
397421
# TODO: maybe deprecate this
398-
result = yield pyfuncitem.obj(**kwargs)
422+
result = yield f(**kwargs)
399423

400424
defer.returnValue(result)
401425

testing/test_basic.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,21 @@ def skip_if_no_async_generators():
9393
)
9494

9595

96+
def skip_if_hypothesis_unavailable():
97+
def hypothesis_unavailable():
98+
try:
99+
import hypothesis # noqa: F401
100+
except ImportError:
101+
return True
102+
103+
return False
104+
105+
return pytest.mark.skipif(
106+
hypothesis_unavailable(),
107+
reason="hypothesis not installed",
108+
)
109+
110+
96111
@pytest.fixture
97112
def cmd_opts(request):
98113
reactor = request.config.getoption("reactor", "default")
@@ -1255,3 +1270,81 @@ def test_should_not_run():
12551270
rr.stdout.no_re_match_line(pat=pattern)
12561271
else:
12571272
assert re.match(pattern, rr.stdout.str()) is None
1273+
1274+
1275+
@skip_if_no_async_await()
1276+
@skip_if_hypothesis_unavailable()
1277+
def test_hypothesis_async_passes(testdir, cmd_opts):
1278+
test_file = """
1279+
import hypothesis
1280+
import hypothesis.strategies
1281+
1282+
import pytest_twisted
1283+
1284+
@hypothesis.given(x=hypothesis.strategies.integers())
1285+
@pytest_twisted.ensureDeferred
1286+
async def test_async(x):
1287+
assert isinstance(x, int)
1288+
"""
1289+
testdir.makepyfile(test_file)
1290+
rr = testdir.run(*cmd_opts, timeout=timeout)
1291+
assert_outcomes(rr, {"passed": 1})
1292+
1293+
1294+
@skip_if_hypothesis_unavailable()
1295+
def test_hypothesis_inline_callbacks_passes(testdir, cmd_opts):
1296+
test_file = """
1297+
import hypothesis
1298+
import hypothesis.strategies
1299+
1300+
import pytest_twisted
1301+
1302+
@hypothesis.given(x=hypothesis.strategies.integers())
1303+
@pytest_twisted.inlineCallbacks
1304+
def test_inline_callbacks(x):
1305+
assert isinstance(x, int)
1306+
return
1307+
yield
1308+
"""
1309+
testdir.makepyfile(test_file)
1310+
rr = testdir.run(*cmd_opts, timeout=timeout)
1311+
assert_outcomes(rr, {"passed": 1})
1312+
1313+
1314+
@skip_if_no_async_await()
1315+
@skip_if_hypothesis_unavailable()
1316+
def test_hypothesis_async_fails(testdir, cmd_opts):
1317+
test_file = """
1318+
import hypothesis
1319+
import hypothesis.strategies
1320+
1321+
import pytest_twisted
1322+
1323+
@hypothesis.given(x=hypothesis.strategies.integers())
1324+
@pytest_twisted.ensureDeferred
1325+
async def test_async(x):
1326+
assert isinstance(x, str)
1327+
"""
1328+
testdir.makepyfile(test_file)
1329+
rr = testdir.run(*cmd_opts, timeout=timeout)
1330+
assert_outcomes(rr, {"failed": 1})
1331+
1332+
1333+
@skip_if_hypothesis_unavailable()
1334+
def test_hypothesis_inline_callbacks_fails(testdir, cmd_opts):
1335+
test_file = """
1336+
import hypothesis
1337+
import hypothesis.strategies
1338+
1339+
import pytest_twisted
1340+
1341+
@hypothesis.given(x=hypothesis.strategies.integers())
1342+
@pytest_twisted.inlineCallbacks
1343+
def test_inline_callbacks(x):
1344+
assert isinstance(x, str)
1345+
return
1346+
yield
1347+
"""
1348+
testdir.makepyfile(test_file)
1349+
rr = testdir.run(*cmd_opts, timeout=timeout)
1350+
assert_outcomes(rr, {"failed": 1})

tox.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ deps=
1111
greenlet
1212
pytest
1313
twisted
14+
py37,py38,py39,pypy37,pypy38: hypothesis
1415
pyqt5reactor,pyside2reactor: pytest-qt
1516
pyqt5reactor,pyside2reactor: pytest-xvfb
1617
pyqt5reactor,pyside2reactor: pywin32; sys_platform == 'win32'

0 commit comments

Comments
 (0)