test(harness): 补 _ladder_units 直测 + 澄清 gate 观测表 unit_id 口径注释
M1:quadrant_pair / gate_evidence 的 question_id 列注释与 write_* docstring 更正为承载 unit_id(single=question_id、pair=pair_id),提示逐题明细在 predictions 表溯源、按 pair_id join 真实 question 表会 join 不上。 M2:给 _ladder_units 补直接单测——纯非 AR 恒等(unit 序==原题序、 unit_id==question_id)、混格交错保持信息阶梯序(按单元最早出现下标重排、 pair 整锁)、且与 build_units 的 single-first 默认序显式区分(防阶梯序被污染)。
This commit is contained in:
@@ -15,7 +15,7 @@ import pytest
|
||||
from app.harness.gate_ladder import BaselineCache, skill_hash
|
||||
from app.harness.inference import PREDICTIONS_SCHEMA, InferenceResult
|
||||
from app.harness.log import HarnessLog
|
||||
from app.harness.validate import validate_skill_local
|
||||
from app.harness.validate import _ladder_units, validate_skill_local
|
||||
from core.evolution import GateParams
|
||||
from core.types import GeneratedQuestion
|
||||
|
||||
@@ -136,6 +136,45 @@ def _make_mock_run_inference(
|
||||
return mock_fn, call_log
|
||||
|
||||
|
||||
class TestLadderUnits:
|
||||
"""_ladder_units:阶梯题序聚合为单元并保持信息阶梯序。"""
|
||||
|
||||
def test_pure_non_ar_is_identity(self) -> None:
|
||||
"""纯非 AR 输入 → 单元序恒等(unit 序==原题序、unit_id==question_id)。"""
|
||||
ladder = [_single("s0"), _single("s1"), _single("s2")]
|
||||
units = _ladder_units(ladder)
|
||||
assert [u.kind for u in units] == ["single", "single", "single"]
|
||||
# unit_id 逐一等于原 question_id,且顺序与输入完全一致
|
||||
assert [u.unit_id for u in units] == ["s0", "s1", "s2"]
|
||||
assert [q.question_id for u in units for q in u.questions] == ["s0", "s1", "s2"]
|
||||
|
||||
def test_mixed_preserves_ladder_order(self) -> None:
|
||||
"""混格交错输入 → 按单元最早出现下标重排,pair 整锁、不被 single-first 污染。"""
|
||||
p1o, p1m = _pair("p1")
|
||||
# 交错布置:pair 两成员分居 idx 1、3;single 分居 idx 0、2、4
|
||||
ladder = [_single("s0"), p1o, _single("s1"), p1m, _single("s2")]
|
||||
units = _ladder_units(ladder)
|
||||
# 最早出现下标:s0=0, p1=min(1,3)=1, s1=2, s2=4 → 阶梯序 [s0,p1,s1,s2]
|
||||
assert [u.unit_id for u in units] == ["s0", "p1", "s1", "s2"]
|
||||
# pair 整锁为一个单元(含两成员),不被拆
|
||||
p1_unit = next(u for u in units if u.unit_id == "p1")
|
||||
assert p1_unit.kind == "pair"
|
||||
assert {q.question_id for q in p1_unit.questions} == {"p1_o", "p1_m"}
|
||||
|
||||
def test_mixed_differs_from_build_units_default(self) -> None:
|
||||
"""混格重排必须纠正 build_units 的 single-first 顺序(否则阶梯序被污染)。"""
|
||||
from app.harness.question_units import build_units
|
||||
|
||||
p1o, p1m = _pair("p1")
|
||||
ladder = [_single("s0"), p1o, _single("s1"), p1m, _single("s2")]
|
||||
default_order = [u.unit_id for u in build_units(ladder)]
|
||||
ladder_order = [u.unit_id for u in _ladder_units(ladder)]
|
||||
# build_units 把 pair 排到 single 之后;_ladder_units 恢复信息阶梯序
|
||||
assert default_order == ["s0", "s1", "s2", "p1"]
|
||||
assert ladder_order == ["s0", "p1", "s1", "s2"]
|
||||
assert ladder_order != default_order
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_gate_n_used_counts_units_not_questions(tmp_path: Path) -> None:
|
||||
"""混格阶梯(1 pair + 2 single)→ n_used=3 单元,非 4 题。"""
|
||||
|
||||
Reference in New Issue
Block a user