"""维度字典:32 项完整性、编号连续、33/34 废弃不复用、初级口径机器可读(T-P3-06)。""" from __future__ import annotations from packages.report.dimensions import ( BASIC_COVERAGE_VALUES, BASIC_COVERED_KEYS, BASIC_FULL_KEYS, DIMENSION_BY_KEY, DIMENSION_BY_NUMBER, DIMENSION_SOURCES, DIMENSIONS, ) #: 需求文档 §4 逐行统计出的初级 full 覆盖集(10 项)——本文件用硬编码预期 #: 对照 BASIC_FULL_KEYS,任何一边漂移都会立刻暴露。 _EXPECTED_BASIC_FULL = { "gender", "height_weight", "birthday", "body_shape", "face_shape", "skin_tone", "season_code", "psyche_style", "fusion_style_name", "core_goals", } #: 初级有产出(full + label + partial)= 21 项,即验收「初级 21/32」口径。 _EXPECTED_BASIC_COVERED_COUNT = 21 def test_exactly_32_dimensions_with_consecutive_numbers() -> None: assert len(DIMENSIONS) == 32 assert [spec.number for spec in DIMENSIONS] == list(range(1, 33)) assert len(DIMENSION_BY_NUMBER) == 32 assert len(DIMENSION_BY_KEY) == 32 def test_keys_unique_and_stable() -> None: keys = [spec.key for spec in DIMENSIONS] assert len(set(keys)) == 32 # 字典键与 kb/记忆系统词汇对齐的锚点抽查。 for anchor in ("body_shape", "face_shape", "season_code"): assert anchor in DIMENSION_BY_KEY def test_retired_numbers_33_34_never_reused() -> None: # TD-31(2026-08-13)移除五行分布/幸运色,编号永久废弃。 assert 33 not in DIMENSION_BY_NUMBER assert 34 not in DIMENSION_BY_NUMBER all_names = "".join(spec.name_cn for spec in DIMENSIONS) assert "五行" not in all_names assert "幸运色" not in all_names def test_enums_legal() -> None: for spec in DIMENSIONS: assert spec.basic_coverage in BASIC_COVERAGE_VALUES assert spec.source in DIMENSION_SOURCES assert spec.name_cn, spec.key def test_basic_full_keys_match_row_by_row_count() -> None: # 机器可读口径 vs 逐行统计:两边必须同时成立。 assert BASIC_FULL_KEYS == _EXPECTED_BASIC_FULL assert ( frozenset(spec.key for spec in DIMENSIONS if spec.basic_coverage == "full") == BASIC_FULL_KEYS ) assert len(BASIC_FULL_KEYS) == 10 def test_basic_covered_keys_is_21_of_32() -> None: derived = frozenset(spec.key for spec in DIMENSIONS if spec.basic_coverage != "none") assert derived == BASIC_COVERED_KEYS assert len(BASIC_COVERED_KEYS) == _EXPECTED_BASIC_COVERED_COUNT assert BASIC_FULL_KEYS <= BASIC_COVERED_KEYS def test_coverage_split_matches_requirement_stats() -> None: # 需求文档 §4 统计表:初级 full 10 / label+partial 11 / none 11,合计 32。 counts = {"full": 0, "label": 0, "partial": 0, "none": 0} for spec in DIMENSIONS: counts[spec.basic_coverage] += 1 assert counts == {"full": 10, "label": 3, "partial": 8, "none": 11}