Skip to content

Commit 5d79bc0

Browse files
authored
Merge pull request #3186 from touilleMan/issue-3185
2 parents af25acd + ecced4c commit 5d79bc0

3 files changed

Lines changed: 94 additions & 0 deletions

File tree

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+
This patch fix invariants display in stateful falsifying examples (:issue:`3185`).

hypothesis-python/src/hypothesis/stateful.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,11 @@ def check_invariants(self, settings):
371371
continue
372372
if not all(precond(self) for precond in invar.preconditions):
373373
continue
374+
if (
375+
current_build_context().is_final
376+
or settings.verbosity >= Verbosity.debug
377+
):
378+
report(f"state.{invar.function.__name__}()")
374379
result = invar.function(self)
375380
if result is not None:
376381
fail_health_check(

hypothesis-python/tests/cover/test_stateful.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,92 @@ def test_foo(self):
597597
run_state_machine_as_test(BadPrecondition)
598598

599599

600+
def test_invariant_failling_present_in_falsifying_example():
601+
@Settings(print_blob=False)
602+
class BadInvariant(RuleBasedStateMachine):
603+
@initialize()
604+
def initialize_1(self):
605+
pass
606+
607+
@invariant()
608+
def invariant_1(self):
609+
raise ValueError()
610+
611+
@rule()
612+
def rule_1(self):
613+
pass
614+
615+
with capture_out() as o:
616+
with pytest.raises(ValueError):
617+
run_state_machine_as_test(BadInvariant)
618+
619+
result = o.getvalue()
620+
assert (
621+
result
622+
== """\
623+
Falsifying example:
624+
state = BadInvariant()
625+
state.initialize_1()
626+
state.invariant_1()
627+
state.teardown()
628+
"""
629+
)
630+
631+
632+
def test_invariant_present_in_falsifying_example():
633+
@Settings(print_blob=False)
634+
class BadRuleWithGoodInvariants(RuleBasedStateMachine):
635+
def __init__(self):
636+
super().__init__()
637+
self.num = 0
638+
639+
@initialize()
640+
def initialize_1(self):
641+
pass
642+
643+
@invariant(check_during_init=True)
644+
def invariant_1(self):
645+
pass
646+
647+
@invariant(check_during_init=False)
648+
def invariant_2(self):
649+
pass
650+
651+
@precondition(lambda self: self.num > 0)
652+
@invariant()
653+
def invariant_3(self):
654+
pass
655+
656+
@rule()
657+
def rule_1(self):
658+
self.num += 1
659+
if self.num == 2:
660+
raise ValueError()
661+
662+
with capture_out() as o:
663+
with pytest.raises(ValueError):
664+
run_state_machine_as_test(BadRuleWithGoodInvariants)
665+
666+
result = o.getvalue()
667+
assert (
668+
result
669+
== """\
670+
Falsifying example:
671+
state = BadRuleWithGoodInvariants()
672+
state.invariant_1()
673+
state.initialize_1()
674+
state.invariant_1()
675+
state.invariant_2()
676+
state.rule_1()
677+
state.invariant_1()
678+
state.invariant_2()
679+
state.invariant_3()
680+
state.rule_1()
681+
state.teardown()
682+
"""
683+
)
684+
685+
600686
def test_always_runs_at_least_one_step():
601687
class CountSteps(RuleBasedStateMachine):
602688
def __init__(self):

0 commit comments

Comments
 (0)