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 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
|
# 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/.
import functools
import warnings
import pytest
from hypothesis import find, given, settings, strategies as st
from hypothesis.errors import HypothesisWarning, InvalidArgument
from hypothesis.internal.validation import check_type
from hypothesis.strategies import (
SearchStrategy as ActualSearchStrategy,
binary,
booleans,
data,
dictionaries,
floats,
frozensets,
integers,
lists,
nothing,
recursive,
sets,
text,
)
from hypothesis.strategies._internal.strategies import check_strategy
from tests.common.debug import check_can_generate_examples, find_any
from tests.common.utils import fails_with
def test_errors_when_given_varargs():
@given(integers())
def has_varargs(*args):
pass
with pytest.raises(InvalidArgument) as e:
has_varargs()
assert "varargs" in e.value.args[0]
def test_varargs_without_positional_arguments_allowed():
@given(somearg=integers())
def has_varargs(somearg, *args):
pass
def test_errors_when_given_varargs_and_kwargs_with_positional_arguments():
@given(integers())
def has_varargs(*args, **kw):
pass
with pytest.raises(InvalidArgument) as e:
has_varargs()
assert "varargs" in e.value.args[0]
def test_varargs_and_kwargs_without_positional_arguments_allowed():
@given(somearg=integers())
def has_varargs(*args, **kw):
pass
def test_bare_given_errors():
@given()
def test():
pass
with pytest.raises(InvalidArgument):
test()
def test_errors_on_unwanted_kwargs():
@given(hello=int, world=int)
def greet(world):
pass
with pytest.raises(InvalidArgument):
greet()
def test_errors_on_too_many_positional_args():
@given(integers(), int, int)
def foo(x, y):
pass
with pytest.raises(InvalidArgument):
foo()
def test_errors_on_any_varargs():
@given(integers())
def oops(*args):
pass
with pytest.raises(InvalidArgument):
oops()
def test_can_put_arguments_in_the_middle():
@given(y=integers())
def foo(x, y, z):
pass
foo(1, 2)
def test_float_ranges():
with pytest.raises(InvalidArgument):
check_can_generate_examples(floats(float("nan"), 0))
with pytest.raises(InvalidArgument):
check_can_generate_examples(floats(1, -1))
def test_float_range_and_allow_nan_cannot_both_be_enabled():
with pytest.raises(InvalidArgument):
check_can_generate_examples(floats(min_value=1, allow_nan=True))
with pytest.raises(InvalidArgument):
check_can_generate_examples(floats(max_value=1, allow_nan=True))
def test_float_finite_range_and_allow_infinity_cannot_both_be_enabled():
with pytest.raises(InvalidArgument):
check_can_generate_examples(floats(0, 1, allow_infinity=True))
def test_does_not_error_if_min_size_is_bigger_than_default_size():
find_any(lists(integers(), min_size=50))
find_any(sets(integers(), min_size=50))
find_any(frozensets(integers(), min_size=50))
find_any(lists(integers(), min_size=50, unique=True))
def test_list_unique_and_unique_by_cannot_both_be_enabled():
@given(lists(integers(), unique=True, unique_by=lambda x: x))
def boom(t):
pass
with pytest.raises(InvalidArgument) as e:
boom()
assert "unique " in e.value.args[0]
assert "unique_by" in e.value.args[0]
def test_min_before_max():
with pytest.raises(InvalidArgument):
integers(min_value=1, max_value=0).validate()
def test_filter_validates():
with pytest.raises(InvalidArgument):
integers(min_value=1, max_value=0).filter(bool).validate()
def test_recursion_validates_base_case():
with pytest.raises(InvalidArgument):
recursive(integers(min_value=1, max_value=0), lists).validate()
def test_recursion_validates_recursive_step():
with pytest.raises(InvalidArgument):
recursive(integers(), lambda x: lists(x, min_size=3, max_size=1)).validate()
@fails_with(InvalidArgument)
@given(x=integers())
def test_stuff_keyword(x=1): # noqa: PT028
pass
@fails_with(InvalidArgument)
@given(integers())
def test_stuff_positional(x=1): # noqa: PT028
pass
@fails_with(InvalidArgument)
@given(integers(), integers())
def test_too_many_positional(x):
pass
def test_given_warns_on_use_of_non_strategies():
@given(bool)
def test(x):
pass
with pytest.raises(InvalidArgument):
test()
def test_given_warns_when_mixing_positional_with_keyword():
@given(booleans(), y=booleans())
def test(x, y):
pass
with pytest.raises(InvalidArgument):
test()
def test_cannot_find_non_strategies():
with pytest.raises(InvalidArgument):
find(bool, bool)
@pytest.mark.parametrize(
"strategy",
[
functools.partial(lists, elements=integers()),
functools.partial(dictionaries, keys=integers(), values=integers()),
text,
binary,
],
)
@pytest.mark.parametrize("min_size,max_size", [(0, "10"), ("0", 10)])
def test_valid_sizes(strategy, min_size, max_size):
@given(strategy(min_size=min_size, max_size=max_size))
def test(x):
pass
with pytest.raises(InvalidArgument):
test()
def test_check_type_with_tuple_of_length_two():
def type_checker(x):
check_type((int, str), x, "x")
type_checker(1)
type_checker("1")
with pytest.raises(InvalidArgument, match="Expected one of int, str but got "):
type_checker(1.0)
def test_validation_happens_on_draw():
@given(data())
def test(data):
data.draw(integers().flatmap(lambda _: lists(nothing(), min_size=1)))
with pytest.raises(InvalidArgument, match="has no values"):
test()
class SearchStrategy:
"""Not the SearchStrategy type you were looking for."""
def check_type_(*args):
return check_type(*args)
def test_check_type_suggests_check_strategy():
check_type_(SearchStrategy, SearchStrategy(), "this is OK")
with pytest.raises(AssertionError, match="use check_strategy instead"):
check_type_(ActualSearchStrategy, None, "SearchStrategy assertion")
def check_strategy_(*args):
return check_strategy(*args)
def test_check_strategy_might_suggest_sampled_from():
with pytest.raises(InvalidArgument) as excinfo:
check_strategy_("not a strategy")
assert "sampled_from" not in str(excinfo.value)
with pytest.raises(InvalidArgument, match="such as st.sampled_from"):
check_strategy_([1, 2, 3])
with pytest.raises(InvalidArgument, match="such as st.sampled_from"):
check_strategy_((1, 2, 3))
check_strategy_(integers(), "passes for our custom coverage check")
@pytest.mark.xfail(
settings._current_profile == "crosshair",
reason=(
"conflicting warning filters. Remove when "
"https://github.com/pschanely/hypothesis-crosshair/issues/42 "
"is fixed"
),
)
@pytest.mark.parametrize("codec", ["ascii", "utf-8"])
def test_warn_on_strings_matching_common_codecs(codec):
with pytest.warns(
HypothesisWarning,
match=f"it seems like you are trying to use the codec {codec!r}",
):
@given(st.text(codec))
def f(s):
pass
f()
# if we reorder, it doesn't warn anymore
with warnings.catch_warnings():
warnings.simplefilter("error")
@given(st.text(codec[1:] + codec[:1]))
def f(s):
pass
f()
|