File: test_searchstrategy.py

package info (click to toggle)
python-hypothesis 6.138.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 15,272 kB
  • sloc: python: 62,853; ruby: 1,107; sh: 253; makefile: 41; javascript: 6
file content (203 lines) | stat: -rw-r--r-- 5,265 bytes parent folder | download
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
# 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 random
import sys
from collections import defaultdict, namedtuple
from dataclasses import dataclass

import attr
import pytest

from hypothesis import given, strategies as st
from hypothesis.errors import InvalidArgument, Unsatisfiable
from hypothesis.internal.conjecture.data import ConjectureData
from hypothesis.internal.reflection import get_pretty_function_description
from hypothesis.strategies._internal.utils import to_jsonable

from tests.common.debug import assert_simple_property, check_can_generate_examples
from tests.common.utils import checks_deprecated_behaviour


def test_or_errors_when_given_non_strategy():
    bools = st.tuples(st.booleans())
    with pytest.raises(ValueError):
        bools | "foo"


SomeNamedTuple = namedtuple("SomeNamedTuple", ("a", "b"))


def last(xs):
    t = None
    for x in xs:
        t = x
    return t


def test_just_strategy_uses_repr():
    class WeirdRepr:
        def __repr__(self):
            return "ABCDEFG"

    assert repr(st.just(WeirdRepr())) == f"just({WeirdRepr()!r})"


def test_just_strategy_does_not_draw():
    data = ConjectureData.for_choices([])
    s = st.just("hello")
    assert s.do_draw(data) == "hello"


def test_none_strategy_does_not_draw():
    data = ConjectureData.for_choices([])
    s = st.none()
    assert s.do_draw(data) is None


def test_can_map():
    s = st.integers().map(pack=lambda t: "foo")
    assert_simple_property(s, lambda v: v == "foo")


def test_example_raises_unsatisfiable_when_too_filtered():
    with pytest.raises(Unsatisfiable):
        check_can_generate_examples(st.integers().filter(lambda x: False))


def nameless_const(x):
    def f(u, v):
        return u

    return functools.partial(f, x)


def test_can_map_nameless():
    f = nameless_const(2)
    assert get_pretty_function_description(f) in repr(st.integers().map(f))


def test_can_flatmap_nameless():
    f = nameless_const(st.just(3))
    assert get_pretty_function_description(f) in repr(st.integers().flatmap(f))


def test_flatmap_with_invalid_expand():
    with pytest.raises(InvalidArgument):
        check_can_generate_examples(st.just(100).flatmap(lambda n: "a"))


_bad_random_strategy = st.lists(st.integers(), min_size=1).map(random.choice)


@checks_deprecated_behaviour
def test_use_of_global_random_is_deprecated_in_given():
    check_can_generate_examples(_bad_random_strategy)


@checks_deprecated_behaviour
def test_use_of_global_random_is_deprecated_in_interactive_draws():
    @given(st.data())
    def inner(d):
        d.draw(_bad_random_strategy)

    inner()


def test_jsonable():
    assert to_jsonable(object(), avoid_realization=True) == "<symbolic>"
    assert isinstance(to_jsonable(object(), avoid_realization=False), str)


@dataclass
class HasDefaultDict:
    x: defaultdict


@attr.s
class AttrsClass:
    n = attr.ib()


def test_jsonable_defaultdict():
    obj = HasDefaultDict(defaultdict(list))
    obj.x["a"] = [42]
    assert to_jsonable(obj, avoid_realization=False) == {"x": {"a": [42]}}


def test_jsonable_attrs():
    obj = AttrsClass(n=10)
    assert to_jsonable(obj, avoid_realization=False) == {"n": 10}


def test_jsonable_namedtuple():
    Obj = namedtuple("Obj", ("x"))
    obj = Obj(10)
    assert to_jsonable(obj, avoid_realization=False) == {"x": 10}


def test_jsonable_small_ints_are_ints():
    n = 2**62
    for avoid in (True, False):
        assert isinstance(to_jsonable(n, avoid_realization=avoid), int)
        assert to_jsonable(n, avoid_realization=avoid) == n


def test_jsonable_large_ints_are_floats():
    n = 2**63
    assert isinstance(to_jsonable(n, avoid_realization=False), float)
    assert to_jsonable(n, avoid_realization=False) == float(n)
    assert to_jsonable(n, avoid_realization=True) == "<symbolic>"


def test_jsonable_very_large_ints():
    # previously caused OverflowError when casting to float.
    n = 2**1024
    assert to_jsonable(n, avoid_realization=False) == sys.float_info.max
    assert to_jsonable(n, avoid_realization=True) == "<symbolic>"


@dataclass
class HasCustomJsonFormat:
    x: str

    def to_json(self):
        return "surprise!"


def test_jsonable_override():
    obj = HasCustomJsonFormat("expected")
    assert to_jsonable(obj, avoid_realization=False) == "surprise!"
    assert to_jsonable(obj, avoid_realization=True) == "<symbolic>"


@dataclass
class Inner:
    value: int

    def to_json(self):
        return "custom"


@dataclass
class Outer:
    inner: Inner


def test_jsonable_to_json_nested():
    obj = Outer(Inner(42))
    assert to_jsonable(obj, avoid_realization=False) == {"inner": "custom"}
    assert to_jsonable(obj, avoid_realization=True) == "<symbolic>"


def test_deferred_strategy_draw():
    strategy = st.deferred(lambda: st.integers())
    assert strategy.do_draw(ConjectureData.for_choices([0])) == 0