Files
Jyotisha/tests/test_real_case_negative_controls.py
2026-07-17 19:51:31 +08:00

62 lines
2.1 KiB
Python

from __future__ import annotations
from scripts.public_real_case_negative_controls import (
generate_control_dates,
parse_offsets,
rank_positive_against_controls,
summarize_negative_control_rows,
)
def test_parse_offsets_rejects_zero_and_deduplicates() -> None:
assert parse_offsets("-60,-30,0,30,60,-30") == (-60, -30, 30, 60)
def test_generate_control_dates_uses_fixed_offsets_without_positive_date() -> None:
dates = generate_control_dates("2018-05-19", offsets=(-60, -30, 30, 60))
assert dates == ["2018-03-20", "2018-04-19", "2018-06-18", "2018-07-18"]
assert "2018-05-19" not in dates
def test_rank_positive_uses_conservative_tie_ordering() -> None:
result = rank_positive_against_controls(5, [7, 5, 4])
assert result == {
"positive_score": 5,
"positive_rank": 3,
"candidate_count": 4,
"reciprocal_rank": 1 / 3,
"top_1": False,
"top_3": True,
"max_control_score": 7,
"score_margin": -2,
}
def test_negative_control_summary_reports_false_activations() -> None:
summary = summarize_negative_control_rows(
[
{
"ranking": {"top_1": True, "top_3": True, "reciprocal_rank": 1.0, "score_margin": 2},
"controls": [{"score": 2}, {"score": 3}],
},
{
"ranking": {"top_1": False, "top_3": True, "reciprocal_rank": 0.5, "score_margin": -1},
"controls": [{"score": 4}, {"score": 7}],
},
]
)
assert summary["case_count"] == 2
assert summary["control_date_count"] == 4
assert summary["control_activation_rate"] == 0.5
assert summary["control_strong_activation_rate"] == 0.25
assert summary["specificity_proxy"] == 0.5
assert summary["strong_specificity_proxy"] == 0.75
assert summary["positive_top_1_rate"] == 0.5
assert summary["positive_top_3_rate"] == 1.0
assert summary["mean_reciprocal_rank"] == 0.75
assert summary["mean_score_margin"] == 0.5
assert summary["timing_precision_gate"]["status"] == "blocked"