"""tests/unit/test_validate.py — 块验证纯决策函数的单元测试。""" import pytest from core.evolution.validate import classify_quadrants, compute_accuracy, pair_block class TestPairBlock: """pair_block 逐题比对基线与候选的翻转统计测试。""" def test_basic_flips(self) -> None: """基本翻转:一题从错到对(w)、一题从对到错(l)、一题不变。""" baseline = {"q1": False, "q2": True, "q3": True} candidate = {"q1": True, "q2": False, "q3": True} result = pair_block(baseline, candidate, ["q1", "q2", "q3"]) assert result.w == 1 assert result.l == 1 assert result.observed == { "q1": (False, True), "q2": (True, False), "q3": (True, True), } def test_empty(self) -> None: """空输入应返回零翻转。""" result = pair_block({}, {}, []) assert result.w == 0 and result.l == 0 def test_all_wins(self) -> None: """全部从错到对的极端情况。""" baseline = {"q1": False, "q2": False} candidate = {"q1": True, "q2": True} result = pair_block(baseline, candidate, ["q1", "q2"]) assert result.w == 2 assert result.l == 0 def test_all_losses(self) -> None: """全部从对到错的极端情况。""" baseline = {"q1": True, "q2": True} candidate = {"q1": False, "q2": False} result = pair_block(baseline, candidate, ["q1", "q2"]) assert result.w == 0 assert result.l == 2 def test_subset_of_questions(self) -> None: """只对 question_ids 中指定的子集进行比对。""" baseline = {"q1": False, "q2": True, "q3": True} candidate = {"q1": True, "q2": False, "q3": True} result = pair_block(baseline, candidate, ["q1"]) assert result.w == 1 assert result.l == 0 assert "q2" not in result.observed class TestClassifyQuadrants: """classify_quadrants 四象限分类测试。""" def test_all_four(self) -> None: """四个象限各有一题。""" observed = { "q1": (False, True), "q2": (True, False), "q3": (False, False), "q4": (True, True), } qc = classify_quadrants(observed) assert qc.improvements == ["q1"] assert qc.regressions == ["q2"] assert qc.persistent_fails == ["q3"] assert qc.stable_successes == ["q4"] def test_sorted_within_quadrant(self) -> None: """同象限内题目 ID 应按字典序排列。""" observed = {"z": (False, True), "a": (False, True)} qc = classify_quadrants(observed) assert qc.improvements == ["a", "z"] def test_empty_observed(self) -> None: """空输入应返回全空象限。""" qc = classify_quadrants({}) assert qc.improvements == [] assert qc.regressions == [] assert qc.persistent_fails == [] assert qc.stable_successes == [] class TestComputeAccuracy: """compute_accuracy 准确率计算测试。""" def test_basic(self) -> None: """一对一错,准确率 0.5。""" assert compute_accuracy({"q1": True, "q2": False}, ["q1", "q2"]) == 0.5 def test_all_correct(self) -> None: """全部正确,准确率 1.0。""" assert compute_accuracy({"q1": True, "q2": True}, ["q1", "q2"]) == 1.0 def test_all_wrong(self) -> None: """全部错误,准确率 0.0。""" assert compute_accuracy({"q1": False, "q2": False}, ["q1", "q2"]) == 0.0 def test_empty_raises(self) -> None: """空题目列表应抛出 ZeroDivisionError。""" with pytest.raises(ZeroDivisionError): compute_accuracy({}, [])