Skip to content

Commit 73a420f

Browse files
lesnik512claude
andcommitted
test(circuit-breaker): make property-test coverage deterministic
The accumulate-advances-with-break loop only exercised the `break` branch when generated advances happened to sum past reset_timeout, which Hypothesis did not hit on every run — intermittently dropping coverage to 99.98% and failing --cov-fail-under=100. Map each clock step to a fraction strictly below reset_timeout instead; no branch, 100% every run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 1336f34 commit 73a420f

1 file changed

Lines changed: 9 additions & 12 deletions

File tree

tests/test_circuit_breaker_props.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ def _request() -> httpx2.Request:
2828
@given(
2929
failure_threshold=st.integers(min_value=1, max_value=5),
3030
reset_timeout=st.floats(min_value=1.0, max_value=100.0),
31-
advances=st.lists(st.floats(min_value=0.0, max_value=0.5), min_size=1, max_size=20),
31+
fractions=st.lists(st.floats(min_value=0.0, max_value=0.99), min_size=1, max_size=20),
3232
)
3333
@settings(max_examples=50, deadline=None)
3434
async def test_open_circuit_never_forwards_before_reset_timeout(
3535
failure_threshold: int,
3636
reset_timeout: float,
37-
advances: list[float],
37+
fractions: list[float],
3838
) -> None:
3939
clock = _Clock()
4040
breaker = AsyncCircuitBreaker(
@@ -52,20 +52,17 @@ async def _ok(request: httpx2.Request) -> httpx2.Response:
5252
async def _five_hundred(request: httpx2.Request) -> httpx2.Response:
5353
raise InternalServerError(httpx2.Response(500, request=request))
5454

55-
# Open the circuit: failure_threshold consecutive 500s.
55+
# Open the circuit while the clock reads 0.0, so opened_at == 0.0.
5656
for _ in range(failure_threshold):
5757
with pytest.raises(InternalServerError):
5858
await breaker(_request(), _five_hundred)
5959

60-
# Now OPEN. Advance the clock in small steps that stay strictly below reset_timeout.
61-
calls_before = forwarded
62-
total = 0.0
63-
for step in advances:
64-
if total + step >= reset_timeout:
65-
break
66-
total += step
67-
clock.t = total
60+
# Now OPEN. Probe at clock times strictly below reset_timeout (fraction <= 0.99), so
61+
# elapsed = clock.t - 0.0 < reset_timeout and every request is rejected without ever
62+
# forwarding to _ok. No conditional branch here — coverage is deterministic across examples.
63+
for fraction in fractions:
64+
clock.t = fraction * reset_timeout
6865
with pytest.raises(CircuitOpenError):
6966
await breaker(_request(), _ok)
7067

71-
assert forwarded == calls_before # `next` (_ok) was never called while OPEN pre-timeout
68+
assert forwarded == 0 # `next` (_ok) was never called while OPEN pre-timeout

0 commit comments

Comments
 (0)