File: test_composite.py

package info (click to toggle)
python-hypothesis 6.67.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 14,220 kB
  • sloc: python: 46,711; ruby: 1,107; sh: 255; xml: 140; makefile: 49; javascript: 12
file content (187 lines) | stat: -rw-r--r-- 5,028 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
# 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 pytest

from hypothesis import assume, given, strategies as st
from hypothesis.errors import HypothesisDeprecationWarning, InvalidArgument

from tests.common.debug import minimal
from tests.common.utils import flaky


@st.composite
def badly_draw_lists(draw, m=0):
    length = draw(st.integers(m, m + 10))
    return [draw(st.integers()) for _ in range(length)]


def test_simplify_draws():
    assert minimal(badly_draw_lists(), lambda x: len(x) >= 3) == [0] * 3


def test_can_pass_through_arguments():
    assert minimal(badly_draw_lists(5), lambda x: True) == [0] * 5
    assert minimal(badly_draw_lists(m=6), lambda x: True) == [0] * 6


@st.composite
def draw_ordered_with_assume(draw):
    x = draw(st.floats())
    y = draw(st.floats())
    assume(x < y)
    return (x, y)


@given(draw_ordered_with_assume())
def test_can_assume_in_draw(xy):
    assert xy[0] < xy[1]


def test_uses_definitions_for_reprs():
    assert repr(badly_draw_lists()) == "badly_draw_lists()"
    assert repr(badly_draw_lists(1)) == "badly_draw_lists(m=1)"
    assert repr(badly_draw_lists(m=1)) == "badly_draw_lists(m=1)"


def test_errors_given_default_for_draw():
    with pytest.raises(InvalidArgument):

        @st.composite
        def foo(x=None):
            pass


def test_errors_given_function_of_no_arguments():
    with pytest.raises(InvalidArgument):

        @st.composite
        def foo():
            pass


def test_errors_given_kwargs_only():
    with pytest.raises(InvalidArgument):

        @st.composite
        def foo(**kwargs):
            pass


def test_warning_given_no_drawfn_call():
    with pytest.warns(HypothesisDeprecationWarning):

        @st.composite
        def foo(_):
            return "bar"


def test_can_use_pure_args():
    @st.composite
    def stuff(*args):
        return args[0](st.sampled_from(args[1:]))

    assert minimal(stuff(1, 2, 3, 4, 5), lambda x: True) == 1


def test_composite_of_lists():
    @st.composite
    def f(draw):
        return draw(st.integers()) + draw(st.integers())

    assert minimal(st.lists(f()), lambda x: len(x) >= 10) == [0] * 10


@flaky(min_passes=2, max_runs=5)
def test_can_shrink_matrices_with_length_param():
    @st.composite
    def matrix(draw):
        rows = draw(st.integers(1, 10))
        columns = draw(st.integers(1, 10))
        return [
            [draw(st.integers(0, 10000)) for _ in range(columns)] for _ in range(rows)
        ]

    def transpose(m):
        return [[row[i] for row in m] for i in range(len(m[0]))]

    def is_square(m):
        return len(m) == len(m[0])

    value = minimal(matrix(), lambda m: is_square(m) and transpose(m) != m)
    assert len(value) == 2
    assert len(value[0]) == 2
    assert sorted(value[0] + value[1]) == [0, 0, 0, 1]


class MyList(list):
    pass


@given(st.data(), st.lists(st.integers()).map(MyList))
def test_does_not_change_arguments(data, ls):
    # regression test for issue #1017 or other argument mutation
    @st.composite
    def strat(draw, arg):
        draw(st.none())
        return arg

    ex = data.draw(strat(ls))
    assert ex is ls


class ClsWithStrategyMethods:
    @classmethod
    @st.composite
    def st_classmethod_then_composite(draw, cls):  # noqa: B902
        return draw(st.integers(0, 10))

    @st.composite
    @classmethod
    def st_composite_then_classmethod(draw, cls):  # noqa: B902
        return draw(st.integers(0, 10))

    @staticmethod
    @st.composite
    def st_staticmethod_then_composite(draw):
        return draw(st.integers(0, 10))

    @st.composite
    @staticmethod
    def st_composite_then_staticmethod(draw):
        return draw(st.integers(0, 10))

    @st.composite
    def st_composite_method(draw, self):  # noqa: B902
        return draw(st.integers(0, 10))


@given(st.data())
def test_applying_composite_decorator_to_methods(data):
    instance = ClsWithStrategyMethods()
    for strategy in [
        ClsWithStrategyMethods.st_classmethod_then_composite(),
        ClsWithStrategyMethods.st_composite_then_classmethod(),
        ClsWithStrategyMethods.st_staticmethod_then_composite(),
        ClsWithStrategyMethods.st_composite_then_staticmethod(),
        instance.st_classmethod_then_composite(),
        instance.st_composite_then_classmethod(),
        instance.st_staticmethod_then_composite(),
        instance.st_composite_then_staticmethod(),
        instance.st_composite_method(),
    ]:
        x = data.draw(strategy)
        assert isinstance(x, int)
        assert 0 <= x <= 10


def test_drawfn_cannot_be_instantiated():
    with pytest.raises(TypeError):
        st.DrawFn()