"""Pure-math tests for stats CI primitives (no I/O).""" from __future__ import annotations import sys from pathlib import Path import pytest sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from scripts.stats import bootstrap_expectancy_ci, wilson_ci # noqa: E402 # --------------------------------------------------------------------------- # Wilson CI # --------------------------------------------------------------------------- class TestWilsonCI: def test_wilson_n_zero(self) -> None: assert wilson_ci(0, 0) == (0.0, 0.0) def test_wilson_perfect_winrate(self) -> None: lo, hi = wilson_ci(10, 10) assert lo > 0.65 assert hi == pytest.approx(1.0, abs=1e-12) def test_wilson_reference_15_55(self) -> None: """wins=8, n=15 (WR≈53%) → CI approximately [29%, 76%] ±2%.""" lo, hi = wilson_ci(8, 15) assert lo == pytest.approx(0.29, abs=0.02) assert hi == pytest.approx(0.76, abs=0.02) def test_wilson_all_losses(self) -> None: lo, hi = wilson_ci(0, 10) assert lo == pytest.approx(0.0, abs=1e-12) assert hi < 0.35 def test_wilson_wins_out_of_range(self) -> None: with pytest.raises(ValueError): wilson_ci(11, 10) with pytest.raises(ValueError): wilson_ci(-1, 10) def test_wilson_clamps_at_50pct_n40(self) -> None: """Reference at WR=50%, N=40: CI ≈ [35.2%, 64.8%].""" lo, hi = wilson_ci(20, 40) assert lo == pytest.approx(0.352, abs=0.005) assert hi == pytest.approx(0.648, abs=0.005) # --------------------------------------------------------------------------- # Bootstrap CI # --------------------------------------------------------------------------- class TestBootstrap: def test_bootstrap_deterministic(self) -> None: values = [1.0, -0.5, 0.5, -1.0] a = bootstrap_expectancy_ci(values, n_resamples=1000, seed=42) b = bootstrap_expectancy_ci(values, n_resamples=1000, seed=42) assert a == b def test_bootstrap_different_seed_different_result(self) -> None: values = [1.0, -0.5, 0.5, -1.0, 0.2, -0.3, 0.5] a = bootstrap_expectancy_ci(values, n_resamples=1000, seed=1) b = bootstrap_expectancy_ci(values, n_resamples=1000, seed=2) assert a != b def test_bootstrap_empty(self) -> None: assert bootstrap_expectancy_ci([], n_resamples=100, seed=0) == (0.0, 0.0) def test_bootstrap_single_value(self) -> None: lo, hi = bootstrap_expectancy_ci([0.5], n_resamples=100, seed=0) assert lo == pytest.approx(0.5, abs=1e-9) assert hi == pytest.approx(0.5, abs=1e-9) def test_bootstrap_brackets_the_mean(self) -> None: values = [0.5, -1.0, 0.5, 0.5, -1.0, 0.2, -0.3, 0.5, -1.0, 0.5] * 5 mean = sum(values) / len(values) lo, hi = bootstrap_expectancy_ci(values, n_resamples=1000, seed=7) assert lo <= mean <= hi