bef46636fe
build_units/flatten_units/validate_units/unit_correctness——pair 契约唯一入口。 build_units 对孤儿/超员/角色缺失重复 fail-fast raise ValueError(防 next 静默 StopIteration);unit_correctness 走 per_q[qid] KeyError 防静默兜底。
74 lines
2.4 KiB
Python
74 lines
2.4 KiB
Python
"""question_units helper 单元测试:组装/展开/校验/单元正确性。
|
||
|
||
覆盖 pair 契约唯一入口的核心行为:
|
||
- build_units 聚合孪生对、保留 single;
|
||
- 孤儿 pair、角色缺失/重复直接报错(fail-fast);
|
||
- flatten_units 无损展开;
|
||
- unit_correctness 对 pair 走 AND、缺题走 KeyError(防静默)。
|
||
"""
|
||
|
||
import pytest
|
||
|
||
from app.harness.question_units import (
|
||
build_units,
|
||
flatten_units,
|
||
unit_correctness,
|
||
validate_units,
|
||
)
|
||
from core.types import GeneratedQuestion
|
||
|
||
|
||
def _q(qid: str, role: str = "single", pid: str | None = None) -> GeneratedQuestion:
|
||
"""构造测试题目;pid 非空时视为孪生对成员。"""
|
||
return GeneratedQuestion(
|
||
question_id=qid,
|
||
video_id="v",
|
||
task_type="AR",
|
||
question="?",
|
||
options=("A. a", "B. b", "C. c", "D. d"),
|
||
answer="A",
|
||
source_nodes=("n",),
|
||
difficulty="hard",
|
||
pair_id=pid,
|
||
question_role=role,
|
||
unit_id=pid or qid,
|
||
flip_axis="ax" if pid else None,
|
||
)
|
||
|
||
|
||
def test_build_units_groups_pair_and_keeps_single():
|
||
qs = [_q("s1"), _q("po", "pair_original", "p"), _q("pm", "pair_mirror", "p")]
|
||
units = build_units(qs)
|
||
kinds = sorted(u.kind for u in units)
|
||
assert kinds == ["pair", "single"]
|
||
|
||
|
||
def test_validate_units_rejects_orphan_pair():
|
||
with pytest.raises(ValueError):
|
||
validate_units(build_units([_q("po", "pair_original", "p")])) # 只 1 条
|
||
|
||
|
||
def test_flatten_roundtrip():
|
||
qs = [_q("po", "pair_original", "p"), _q("pm", "pair_mirror", "p")]
|
||
assert {q.question_id for q in flatten_units(build_units(qs))} == {"po", "pm"}
|
||
|
||
|
||
def test_unit_correctness_bidirectional_and():
|
||
qs = [_q("po", "pair_original", "p"), _q("pm", "pair_mirror", "p")]
|
||
u = build_units(qs)[0]
|
||
assert unit_correctness(u, {"po": True, "pm": True}) is True
|
||
assert unit_correctness(u, {"po": True, "pm": False}) is False # AND
|
||
|
||
|
||
def test_build_units_rejects_duplicate_role():
|
||
qs = [_q("po1", "pair_original", "p"), _q("po2", "pair_original", "p")]
|
||
with pytest.raises(ValueError):
|
||
build_units(qs)
|
||
|
||
|
||
def test_unit_correctness_missing_question_raises_keyerror():
|
||
qs = [_q("po", "pair_original", "p"), _q("pm", "pair_mirror", "p")]
|
||
u = build_units(qs)[0]
|
||
with pytest.raises(KeyError):
|
||
unit_correctness(u, {"po": True}) # 缺 pm → KeyError 防静默
|