Skip to content

Commit a509843

Browse files
authored
Merge pull request #4539 from Liam-DeVoe/next2
Improve error message for `DeadlineExceeded`
2 parents db13c04 + 3e11cf0 commit a509843

File tree

5 files changed

+39
-35
lines changed

5 files changed

+39
-35
lines changed

hypothesis-python/RELEASE.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
RELEASE_TYPE: patch
2+
3+
Improved error message for |DeadlineExceeded|.

hypothesis-python/docs/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ Hypothesis is the property-based testing library for Python. With Hypothesis, yo
5656
5757
test_sort_correct()
5858
59-
You should start with the :doc:`tutorial <tutorial/index>`, or the more condensed :doc:`quickstart <quickstart>`.
59+
You should start with the :doc:`tutorial <tutorial/index>`, or alternatively the more condensed :doc:`quickstart <quickstart>`.
6060

6161
.. rst-class:: row
6262

hypothesis-python/src/hypothesis/errors.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,9 @@ class DeadlineExceeded(_Trimmable):
243243
def __init__(self, runtime: timedelta, deadline: timedelta) -> None:
244244
super().__init__(
245245
f"Test took {runtime.total_seconds() * 1000:.2f}ms, which exceeds "
246-
f"the deadline of {deadline.total_seconds() * 1000:.2f}ms"
246+
f"the deadline of {deadline.total_seconds() * 1000:.2f}ms. If you "
247+
"expect test cases to take this long, you can use @settings(deadline=...) "
248+
"to either set a higher deadline, or to disable it with deadline=None."
247249
)
248250
self.runtime = runtime
249251
self.deadline = deadline

hypothesis-python/tests/nocover/test_stateful.py

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ def split(self, left, right):
6363
def test_is_balanced(self, tree):
6464
if isinstance(tree, Leaf):
6565
return
66-
else:
67-
assert abs(self.size(tree.left) - self.size(tree.right)) <= 1
68-
self.test_is_balanced(tree.left)
69-
self.test_is_balanced(tree.right)
66+
67+
assert abs(self.size(tree.left) - self.size(tree.right)) <= 1
68+
self.test_is_balanced(tree.left)
69+
self.test_is_balanced(tree.right)
7070

7171
def size(self, tree):
7272
if isinstance(tree, Leaf):
@@ -108,13 +108,10 @@ def bunch(self, source):
108108

109109
@rule(source=nodes)
110110
def shallow(self, source):
111-
def d(ls):
112-
if not ls:
113-
return 0
114-
else:
115-
return 1 + max(map(d, ls))
111+
def depth(ls):
112+
return 0 if not ls else 1 + max(map(depth, ls))
116113

117-
assert d(source) <= 5
114+
assert depth(source) <= 5
118115

119116

120117
class NotTheLastMachine(RuleBasedStateMachine):
@@ -166,11 +163,7 @@ def __init__(self):
166163
super().__init__()
167164
self.seen = set()
168165

169-
# The reason this rule takes a parameter is that it ensures that we do not
170-
# achieve "swarming" by by just restricting the alphabet for single byte
171-
# decisions, which is a thing the underlying conjecture engine will
172-
# happily do on its own without knowledge of the rule structure.
173-
@rule(move=st.integers(0, 255))
166+
@rule(move=st.integers())
174167
def ladder(self, move):
175168
self.seen.add(move)
176169
assert len(self.seen) <= 15
@@ -190,16 +183,12 @@ def snake(self):
190183
)
191184

192185
for m in bad_machines:
193-
m.TestCase.settings = Settings(m.TestCase.settings, max_examples=1000)
194-
195-
196-
cheap_bad_machines = list(bad_machines)
197-
cheap_bad_machines.remove(BalancedTrees)
198-
199-
200-
with_cheap_bad_machines = pytest.mark.parametrize(
201-
"machine", cheap_bad_machines, ids=[t.__name__ for t in cheap_bad_machines]
202-
)
186+
m.TestCase.settings = Settings(
187+
m.TestCase.settings,
188+
max_examples=1000,
189+
database=None,
190+
phases=set(Phase) - {Phase.shrink},
191+
)
203192

204193

205194
@pytest.mark.parametrize(
@@ -213,14 +202,8 @@ def test_bad_machines_fail(machine):
213202
# and also takes 10/6 minutes respectively, on top of not finding the failure
214203
pytest.xfail(reason=str(Why.undiscovered))
215204

216-
test_class = machine.TestCase
217-
try:
218-
test_class().runTest()
219-
raise RuntimeError("Expected an assertion error")
220-
except AssertionError as err:
221-
notes = err.__notes__
222-
steps = [l for l in notes if "Step " in l or "state." in l]
223-
assert 1 <= len(steps) <= 50
205+
with pytest.raises(AssertionError):
206+
machine.TestCase().runTest()
224207

225208

226209
class MyStatefulMachine(RuleBasedStateMachine):

hypothesis-python/tests/patching/test_patching.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,22 @@ def test_no_example_for_data_strategy():
190190
assert get_patch_for(fn, [("fn(Foo(data=data(...)))", "msg")]) is not None
191191

192192

193+
def test_patch_order_preserved():
194+
(_fname, _before, after) = get_patch_for(
195+
fn, [("fn(a=1)", "msg"), ("fn(b=2)", "msg")]
196+
)
197+
assert after.startswith(
198+
'@given(st.integers())\n@example(a=1).via("msg")\n@example(b=2).via("msg")'
199+
)
200+
201+
(_fname, _before, after) = get_patch_for(
202+
fn, [("fn(b=2)", "msg"), ("fn(a=1)", "msg")]
203+
)
204+
assert after.startswith(
205+
'@given(st.integers())\n@example(b=2).via("msg")\n@example(a=1).via("msg")'
206+
)
207+
208+
193209
def test_deduplicates_examples():
194210
tst, example, expected = SIMPLE
195211
where, _, after = get_patch_for(tst, [example, example])

0 commit comments

Comments
 (0)