Skip to content

Commit 2bca570

Browse files
committed
Add note to NonInteracteExampleWarning in selftests
1 parent d93ec6d commit 2bca570

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

hypothesis-python/tests/conftest.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import pytest
1818

1919
from hypothesis._settings import is_in_ci
20+
from hypothesis.errors import NonInteractiveExampleWarning
21+
from hypothesis.internal.compat import add_note
2022
from hypothesis.internal.detection import is_hypothesis_test
2123

2224
from tests.common import TIME_INCREMENT
@@ -106,20 +108,20 @@ def pytest_runtest_call(item):
106108
# This hookwrapper checks for PRNG state leaks from Hypothesis tests.
107109
# See: https://github.com/HypothesisWorks/hypothesis/issues/1919
108110
if not (hasattr(item, "obj") and is_hypothesis_test(item.obj)):
109-
yield
111+
outcome = yield
110112
elif "pytest_randomly" in sys.modules:
111113
# See https://github.com/HypothesisWorks/hypothesis/issues/3041 - this
112114
# branch exists to make it easier on external contributors, but should
113115
# never run in our CI (because that would disable the check entirely).
114116
assert not is_in_ci()
115-
yield
117+
outcome = yield
116118
else:
117119
# We start by peturbing the state of the PRNG, because repeatedly
118120
# leaking PRNG state resets state_after to the (previously leaked)
119121
# state_before, and that just shows as "no use of random".
120122
random.seed(independent_random.randrange(2**32))
121123
before = random.getstate()
122-
yield
124+
outcome = yield
123125
after = random.getstate()
124126
if before != after:
125127
if after in random_states_after_tests:
@@ -129,3 +131,11 @@ def pytest_runtest_call(item):
129131
"same global `random.getstate()`; this is probably a nasty bug!"
130132
)
131133
random_states_after_tests[after] = item.nodeid
134+
135+
# Annotate usage of .example() with a hint about alternatives
136+
if isinstance(outcome.exception, NonInteractiveExampleWarning):
137+
add_note(
138+
outcome.exception,
139+
"For hypothesis' own test suite, consider using one of the helper "
140+
"methods in tests.common.debug instead.",
141+
)

hypothesis-python/tests/cover/test_interactive_example.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
from tests.common.debug import find_any
2828
from tests.common.utils import fails_with
2929

30+
pytest_plugins = "pytester"
31+
3032

3133
# Allow calling .example() without warnings for all tests in this module
3234
@pytest.fixture(scope="function", autouse=True)
@@ -84,6 +86,27 @@ def test_non_interactive_example_emits_warning():
8486
st.text().example()
8587

8688

89+
EXAMPLE_GENERATING_TEST = """
90+
from hypothesis import strategies as st
91+
92+
def test_interactive_example():
93+
st.integers().example()
94+
"""
95+
96+
97+
def test_selftests_exception_contains_note(pytester):
98+
# The note is added by a pytest hook, so we need to run it under pytest in a
99+
# subenvironment with (effectively) the same toplevel conftest.
100+
with warnings.catch_warnings():
101+
warnings.simplefilter("error")
102+
103+
pytester.makeconftest("from tests.conftest import *")
104+
result = pytester.runpytest_inprocess(
105+
pytester.makepyfile(EXAMPLE_GENERATING_TEST)
106+
)
107+
assert "helper methods in tests.common.debug" in "\n".join(result.outlines)
108+
109+
87110
@pytest.mark.skipif(WINDOWS, reason="pexpect.spawn not supported on Windows")
88111
def test_interactive_example_does_not_emit_warning():
89112
try:

0 commit comments

Comments
 (0)