Skip to content

Commit 0b3d4ab

Browse files
Евгений БлиновЕвгений Блинов
authored andcommitted
Add tests for Scenario constructor validation and percentile constraints
1 parent 84f587e commit 0b3d4ab

1 file changed

Lines changed: 67 additions & 0 deletions

File tree

tests/documentation/test_readme.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import math
44
from functools import partial
55

6+
import pytest
7+
68
from microbenchmark import BenchmarkResult, Scenario, ScenarioGroup
79

810

@@ -147,6 +149,71 @@ def test_p99_cached(self) -> None:
147149
assert result.p99 is result.p99
148150

149151

152+
class TestScenarioConstructorValidation:
153+
def test_number_zero_raises(self) -> None:
154+
# README: "passing 0 or a negative value raises ValueError"
155+
with pytest.raises(ValueError):
156+
Scenario(lambda: None, name='s', number=0)
157+
158+
def test_number_negative_raises(self) -> None:
159+
with pytest.raises(ValueError):
160+
Scenario(lambda: None, name='s', number=-1)
161+
162+
def test_args_none_and_empty_list_equivalent(self) -> None:
163+
# README: "None (the default) and [] both mean the function is called with no arguments"
164+
calls_none: list[tuple[object, ...]] = []
165+
calls_empty: list[tuple[object, ...]] = []
166+
167+
def fn_none(*a: object) -> None:
168+
calls_none.append(a)
169+
170+
def fn_empty(*a: object) -> None:
171+
calls_empty.append(a)
172+
173+
Scenario(fn_none, args=None, name='s', number=1).run()
174+
Scenario(fn_empty, args=[], name='s', number=1).run()
175+
assert calls_none == [()]
176+
assert calls_empty == [()]
177+
178+
def test_args_shallow_copied(self) -> None:
179+
# README: "The list is shallow-copied on construction"
180+
original = [1, 2]
181+
s = Scenario(lambda *_: None, args=original, name='s', number=1)
182+
original.append(3)
183+
call_log: list[tuple[object, ...]] = []
184+
185+
def fn(*a: object) -> None:
186+
call_log.append(a)
187+
188+
Scenario(fn, args=[1, 2], name='s', number=1).run()
189+
assert call_log == [(1, 2)] # mutation after construction has no effect
190+
191+
def test_custom_timer(self) -> None:
192+
# README: "Supply a custom clock to get deterministic measurements in tests"
193+
tick = [0.0]
194+
195+
def fake_timer() -> float:
196+
tick[0] += 0.001
197+
return tick[0]
198+
199+
result = Scenario(lambda: None, name='s', number=5, timer=fake_timer).run()
200+
assert len(result.durations) == 5
201+
assert all(d > 0 for d in result.durations)
202+
203+
204+
class TestPercentileValidation:
205+
def test_percentile_zero_raises(self) -> None:
206+
# README: "passing 0 or a value above 100 raises ValueError"
207+
result = Scenario(lambda: None, name='noop', number=10).run()
208+
with pytest.raises(ValueError):
209+
result.percentile(0)
210+
211+
def test_percentile_above_100_raises(self) -> None:
212+
result = Scenario(lambda: None, name='noop', number=10).run()
213+
with pytest.raises(ValueError):
214+
result.percentile(101)
215+
216+
150217
class TestJsonRoundTrip:
151218
def test_json_round_trip(self) -> None:
152219
result = Scenario(lambda: None, name='noop', number=100).run()

0 commit comments

Comments
 (0)