-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_.py
134 lines (104 loc) · 3.14 KB
/
test_.py
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
"""Tests for autosig."""
from attr import asdict
from autosig import Signature, autosig, param
from autosig.autosig import make_sig_class
from functools import partial
from hypothesis import (
HealthCheck,
PrintSettings,
assume,
given,
# reproduce_failure,
settings,
unlimited,
)
from hypothesis.strategies import builds, text, dictionaries
from inspect import signature
from pytest import raises
from string import ascii_letters, punctuation
# hypothesis strategy for identifiers
# min_size is 5 to avoid hitting reserved words by mistake
identifiers = partial(text, alphabet=ascii_letters, min_size=5, max_size=10)
docstrings = partial(
text, alphabet=ascii_letters + punctuation + " \n", min_size=25, max_size=50
)
def params():
"""Generate params.
Returns
-------
Hypothesis strategy
Strategy to generate params.
"""
return builds(param, default=text(), docstring=docstrings())
def signatures():
"""Generate signatures.
Returns
-------
Hypothesis strategy
Strategy to generate signatures.
"""
return builds(
lambda x: Signature(**x), dictionaries(keys=identifiers(), values=params())
)
settings.register_profile(
"this",
timeout=unlimited,
suppress_health_check=[HealthCheck.too_slow],
print_blob=PrintSettings.ALWAYS,
)
settings.load_profile("this")
@given(sig=signatures())
def test_decorated_call(sig):
"""Autosig-decorated functions accept a compatible set of arguments."""
Sig = make_sig_class(sig)
autosig(sig)(Sig)(**asdict(Sig()))
@given(sig1=signatures(), sig2=signatures())
def test_decorator_fails(sig1, sig2):
"""Autosig-decorated functions fail on an incompatible signature."""
Sig1 = make_sig_class(sig1)
Sig2 = make_sig_class(sig2)
assume(signature(Sig1).parameters != signature(Sig2).parameters)
deco = autosig(sig1)
try:
deco(Sig2)
except Exception:
return
raise Exception
@given(sig1=signatures(), sig2=signatures())
def test_decorated_call_fails(sig1, sig2):
"""Autosig-decorated functions fail on a call with incompatible arguments."""
Sig1 = make_sig_class(sig1)
Sig2 = make_sig_class(sig2)
assume(
not set(signature(Sig2).parameters.keys())
<= set(signature(Sig1).parameters.keys())
)
f = autosig(sig1)(Sig1)
try:
f(**asdict(Sig2()))
except Exception:
return
raise Exception
@given(sig1=signatures(), sig2=signatures())
def test_signature_addition(sig1, sig2):
"""Combine two signatures"""
assert (sig1 + sig2).params == dict(sig1.params, **sig2.params)
def test_argumentless_decorator():
"Non-randomized test for argumentless decorator"
@autosig
def fun(a=param(validator=int)):
pass
fun(1)
with raises(
AssertionError,
match="type of a = 1.0 should be <class 'int'>, <class 'float'> found instead",
):
fun(1.0)
def test_decorated_method():
"""Non-randomized test for method decorator
"""
class C:
@autosig(Signature(a=param(converter=int)))
def method(self, a):
return a
assert C().method(1.1) == 1