1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
|
# This file is part of Hypothesis, which may be found at
# https://github.com/HypothesisWorks/hypothesis/
#
# Copyright the Hypothesis Authors.
# Individual contributors are listed in AUTHORS.rst and the git log.
#
# This Source Code Form is subject to the terms of the Mozilla Public License,
# v. 2.0. If a copy of the MPL was not distributed with this file, You can
# obtain one at https://mozilla.org/MPL/2.0/.
from dataclasses import dataclass
import pytest
from hypothesis import Verbosity, assume, given, reject, reporting, settings
from hypothesis.control import (
BuildContext,
_current_build_context,
_event_to_string,
cleanup,
current_build_context,
currently_in_test_context,
event,
note,
)
from hypothesis.errors import (
HypothesisDeprecationWarning,
InvalidArgument,
UnsatisfiedAssumption,
)
from hypothesis.internal.compat import ExceptionGroup
from hypothesis.internal.conjecture.data import ConjectureData
from hypothesis.stateful import RuleBasedStateMachine, rule
from hypothesis.strategies import integers
from tests.common.utils import capture_out
def bc():
return BuildContext(ConjectureData.for_choices([]), wrapped_test=None)
def test_cannot_cleanup_with_no_context():
with pytest.raises(InvalidArgument):
cleanup(lambda: None)
assert _current_build_context.value is None
def test_cannot_event_with_no_context():
with pytest.raises(InvalidArgument):
event("hi")
assert _current_build_context.value is None
def test_cleanup_executes_on_leaving_build_context():
data = []
with bc():
cleanup(lambda: data.append(1))
assert not data
assert data == [1]
assert _current_build_context.value is None
def test_can_nest_build_context():
data = []
with bc():
cleanup(lambda: data.append(1))
with bc():
cleanup(lambda: data.append(2))
assert not data
assert data == [2]
assert data == [2, 1]
assert _current_build_context.value is None
def test_does_not_suppress_exceptions():
with pytest.raises(AssertionError):
# NOTE: For compatibility with Python 3.9's LL(1)
# parser, this is written as a nested with-statement,
# instead of a compound one.
with bc():
raise AssertionError
assert _current_build_context.value is None
def test_suppresses_exceptions_in_teardown():
with pytest.raises(ValueError) as exc_info:
# NOTE: For compatibility with Python 3.9's LL(1)
# parser, this is written as a nested with-statement,
# instead of a compound one.
with bc():
def foo():
raise ValueError
cleanup(foo)
raise AssertionError
assert isinstance(exc_info.value, ValueError)
assert isinstance(exc_info.value.__cause__, AssertionError)
def test_runs_multiple_cleanup_with_teardown():
with pytest.raises(ExceptionGroup) as exc_info:
# NOTE: For compatibility with Python 3.9's LL(1)
# parser, this is written as a nested with-statement,
# instead of a compound one.
with bc():
def foo():
raise ValueError
def bar():
raise TypeError
cleanup(foo)
cleanup(bar)
raise AssertionError
assert isinstance(exc_info.value, ExceptionGroup)
assert isinstance(exc_info.value.__cause__, AssertionError)
assert {type(e) for e in exc_info.value.exceptions} == {ValueError, TypeError}
assert _current_build_context.value is None
def test_raises_error_if_cleanup_fails_but_block_does_not():
with pytest.raises(ValueError):
# NOTE: For compatibility with Python 3.9's LL(1)
# parser, this is written as a nested with-statement,
# instead of a compound one.
with bc():
def foo():
raise ValueError
cleanup(foo)
assert _current_build_context.value is None
def test_raises_if_note_out_of_context():
with pytest.raises(InvalidArgument):
note("Hi")
def test_deprecation_warning_if_assume_out_of_context():
with pytest.warns(
HypothesisDeprecationWarning,
match="Using `assume` outside a property-based test is deprecated",
):
assume(True)
def test_deprecation_warning_if_reject_out_of_context():
with pytest.warns(
HypothesisDeprecationWarning,
match="Using `reject` outside a property-based test is deprecated",
):
with pytest.raises(UnsatisfiedAssumption):
reject()
def test_raises_if_current_build_context_out_of_context():
with pytest.raises(InvalidArgument):
current_build_context()
def test_current_build_context_is_current():
with bc() as a:
assert current_build_context() is a
def test_prints_all_notes_in_verbose_mode():
# slightly roundabout because @example messes with verbosity - see #1521
messages = set()
@settings(verbosity=Verbosity.debug, database=None)
@given(integers(1, 10))
def test(x):
msg = f"x -> {x}"
note(msg)
messages.add(msg)
assert x < 5
with capture_out() as out:
# NOTE: For compatibility with Python 3.9's LL(1)
# parser, this is written as a nested with-statement,
# instead of a compound one.
with reporting.with_reporter(reporting.default):
with pytest.raises(AssertionError):
test()
v = out.getvalue()
for x in sorted(messages):
assert x in v
@dataclass
class CanBePrettyPrinted:
n: int
def test_note_pretty_prints():
reports = []
@given(integers(1, 10))
def test(n):
with reporting.with_reporter(reports.append):
note(CanBePrettyPrinted(n))
assert n != 5
with pytest.raises(AssertionError):
test()
assert reports == ["CanBePrettyPrinted(n=5)"]
def test_not_currently_in_hypothesis():
assert currently_in_test_context() is False
@given(integers())
def test_currently_in_hypothesis(_):
assert currently_in_test_context() is True
class ContextMachine(RuleBasedStateMachine):
@rule()
def step(self):
assert currently_in_test_context() is True
test_currently_in_stateful_test = ContextMachine.TestCase
def test_can_convert_non_weakref_types_to_event_strings():
_event_to_string(())
|