Skip to content

Commit 572ac0e

Browse files
committed
check
1 parent 99f0954 commit 572ac0e

File tree

2 files changed

+160
-2
lines changed

2 files changed

+160
-2
lines changed

codeflash/verification/hypothesis_testing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,10 @@ def visit_Call(self, node: ast.Call) -> ast.Call:
150150
elif node.func.attr == "integers" and not any(
151151
k.arg in ["min_value", "max_value"] for k in node.keywords
152152
):
153-
# Constrain integers to reasonable bounds
153+
# Constrain integers to reasonable bounds (including negatives)
154154
node.keywords.extend(
155155
[
156-
ast.keyword(arg="min_value", value=ast.Constant(value=0)),
156+
ast.keyword(arg="min_value", value=ast.Constant(value=-10000)),
157157
ast.keyword(
158158
arg="max_value", value=ast.Constant(value=10000)
159159
),

tests/test_hypothesis_testing.py

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
"""Tests for hypothesis_testing.py functions."""
2+
3+
from codeflash.verification.hypothesis_testing import make_hypothesis_tests_deterministic
4+
5+
6+
def test_adds_derandomize_decorator():
7+
"""Test that @settings(derandomize=True) is added when missing."""
8+
src = """
9+
from hypothesis import given, strategies as st
10+
11+
@given(x=st.integers())
12+
def test_x(x):
13+
assert isinstance(x, int)
14+
"""
15+
out = make_hypothesis_tests_deterministic(src)
16+
assert "@settings(derandomize=True)" in out or "settings(derandomize=True)" in out
17+
18+
19+
def test_integers_constrained_with_negatives():
20+
"""Test that st.integers() gets bounded to [-10000, 10000]."""
21+
src = """from hypothesis import given, strategies as st
22+
@given(x=st.integers())
23+
def t(x):
24+
pass
25+
"""
26+
out = make_hypothesis_tests_deterministic(src)
27+
# Remove spaces for easier checking
28+
normalized = out.replace(" ", "").replace("\n", "")
29+
assert "min_value=-10000" in normalized
30+
assert "max_value=10000" in normalized
31+
32+
33+
def test_floats_constrained_to_finite():
34+
"""Test that st.floats() is constrained to finite values with bounds."""
35+
src = """from hypothesis import given, strategies as st
36+
@given(x=st.floats())
37+
def t(x):
38+
pass
39+
"""
40+
out = make_hypothesis_tests_deterministic(src)
41+
normalized = out.replace(" ", "").replace("\n", "")
42+
assert "allow_nan=False" in normalized
43+
assert "allow_infinity=False" in normalized
44+
assert "min_value=" in normalized and "max_value=" in normalized
45+
46+
47+
def test_existing_constraints_not_overridden():
48+
"""Test that existing constraints on strategies are preserved."""
49+
src = """from hypothesis import given, strategies as st, settings
50+
51+
@settings(derandomize=True, max_examples=5)
52+
@given(x=st.integers(min_value=-5, max_value=5))
53+
def t(x):
54+
pass
55+
"""
56+
out = make_hypothesis_tests_deterministic(src)
57+
# Should not add duplicate settings decorator
58+
assert out.count("@settings") == 1
59+
# Should preserve original constraints
60+
assert "min_value=-5" in out or "min_value= -5" in out
61+
assert "max_value=5" in out or "max_value= 5" in out
62+
# Should not add the default -10000/10000 bounds
63+
assert "-10000" not in out
64+
65+
66+
def test_existing_float_constraints_preserved():
67+
"""Test that existing float constraints are not overridden."""
68+
src = """from hypothesis import given, strategies as st
69+
70+
@given(y=st.floats(min_value=-1.0, max_value=1.0, allow_nan=False, allow_infinity=False))
71+
def t(y):
72+
pass
73+
"""
74+
out = make_hypothesis_tests_deterministic(src)
75+
assert "min_value=-1.0" in out or "min_value= -1.0" in out
76+
assert "max_value=1.0" in out or "max_value= 1.0" in out
77+
# Should not add the default 1e6 bounds
78+
assert "1e6" not in out and "1000000" not in out
79+
80+
81+
def test_idempotency():
82+
"""Test that running the function twice produces the same result."""
83+
src = """from hypothesis import given, strategies as st
84+
85+
@given(x=st.integers(), y=st.floats())
86+
def test_func(x, y):
87+
pass
88+
"""
89+
out1 = make_hypothesis_tests_deterministic(src)
90+
out2 = make_hypothesis_tests_deterministic(out1)
91+
assert out1 == out2
92+
93+
94+
def test_multiple_strategies_handled():
95+
"""Test that multiple strategies in one test are all constrained."""
96+
src = """from hypothesis import given, strategies as st
97+
98+
@given(a=st.integers(), b=st.integers(), c=st.floats())
99+
def test_multi(a, b, c):
100+
pass
101+
"""
102+
out = make_hypothesis_tests_deterministic(src)
103+
normalized = out.replace(" ", "").replace("\n", "")
104+
# All integers should be constrained
105+
assert normalized.count("min_value=-10000") >= 2
106+
assert normalized.count("max_value=10000") >= 2
107+
# Float should be constrained
108+
assert "allow_nan=False" in normalized
109+
assert "allow_infinity=False" in normalized
110+
111+
112+
def test_settings_import_added_if_missing():
113+
"""Test that 'from hypothesis import settings' is added when needed."""
114+
src = """from hypothesis import given, strategies as st
115+
116+
@given(x=st.integers())
117+
def test_x(x):
118+
pass
119+
"""
120+
out = make_hypothesis_tests_deterministic(src)
121+
# Should have settings import or settings in existing import
122+
assert "settings" in out
123+
124+
125+
def test_partial_constraints_completed():
126+
"""Test that partial constraints are completed."""
127+
src = """from hypothesis import given, strategies as st
128+
129+
@given(x=st.integers(min_value=100))
130+
def test_x(x):
131+
pass
132+
"""
133+
out = make_hypothesis_tests_deterministic(src)
134+
# Should keep the min_value=100 and not override
135+
assert "min_value=100" in out or "min_value= 100" in out
136+
# Should not add default bounds since min_value exists
137+
assert "-10000" not in out
138+
139+
140+
def test_syntax_error_returns_original():
141+
"""Test that invalid Python syntax returns original code unchanged."""
142+
invalid_src = "this is not valid python @#$%"
143+
out = make_hypothesis_tests_deterministic(invalid_src)
144+
assert out == invalid_src
145+
146+
147+
def test_no_hypothesis_code_unchanged():
148+
"""Test that code without hypothesis is returned mostly unchanged."""
149+
src = """def regular_function(x):
150+
return x * 2
151+
152+
def test_regular():
153+
assert regular_function(2) == 4
154+
"""
155+
out = make_hypothesis_tests_deterministic(src)
156+
# Should still parse and return valid code
157+
assert "def regular_function" in out
158+
assert "def test_regular" in out

0 commit comments

Comments
 (0)