Files
Aislo/resources/tester/test_b05_not_in_table_marks.py

111 lines
4.3 KiB
Python

# -*- coding: utf-8 -*-
"""「칸은 있는데 표가 안 읽음」 — 등록부 칸 옆에 「아직 표에 안 쓰임」 (2026-09-14 브레인 차례 ①).
사용자가 값을 넣어도 수량·금액이 아무것도 안 바뀌는 칸. 사유를 표에만 두지 말고 칸 옆에도 보임
(브레인 판정 ③ 「B」). 표시가 참말인지 **값을 바꿔 돌려 보고** 지킴 — 표가 그 칸을 읽기 시작하면
여기서 깨지고, 그때 표시를 걷음(표시가 거짓말로 남지 않게).
"""
from __future__ import annotations
import json
import sys
from pathlib import Path
import pytest
ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from B05_Profile.B05_Profile_Structures_Schema import structure_type_map # noqa: E402
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table # noqa: E402
#: 종류 → (표가 서는 기준 제원, 안 읽는 칸). 2026-09-14 값을 바꿔 전수 대조한 결과.
#: ⚠ 기초(foundation)·높이는 인계 구조물터파기 심도 구간이 읽어 뺌 · 단 수·올림·이동은 횡단도 칸이라 뺌.
MARKED: dict[str, tuple[dict, list[str]]] = {
"erosion_check": (
{"height_m": 2.0, "top_length_m": 6.0, "bottom_length_m": 4.0, "form": "돌"},
["thickness_top_m", "thickness_bottom_m", "stone_supply", "stone_coeff_basis"],
),
"bed_sill": (
{"area_m2": 10.0, "form": "돌붙임(찰)"},
["stone_supply", "stone_coeff_basis", "fill_concrete_mpa", "face_slope_ratio"],
),
"boulder_masonry": (
{"height_m": 2.5, "length_m": 10.0, "stone_cm": "60~80", "bond": "찰쌓기"},
[
"stone_supply",
"stone_coeff_basis",
"fill_concrete_mpa",
"weep_hole_diameter_mm",
"weep_hole_area_m2",
],
),
"soil_guard": (
{"height_m": 1.0, "length_m": 10.0, "form": "떼"},
[
"thickness_top_m",
"thickness_bottom_m",
"back_len_cm",
"stone_kind",
"stone_supply",
"stone_coeff_basis",
"fill_concrete_mpa",
"face_slope_ratio",
"weep_hole_diameter_mm",
"weep_hole_area_m2",
],
),
}
FIELDS = (ROOT / "B05_Profile" / "B05_Profile_UI_Structures_Fields.ts").read_text(encoding="utf-8")
PANEL = (ROOT / "B05_Profile" / "B05_Profile_UI_Structures_Panel.ts").read_text(encoding="utf-8")
def _snapshot(type_id: str, options: dict) -> str:
structure = {
"structure_id": "p",
"type_id": type_id,
"start_m": 0.0,
"end_m": 10.0,
"chainage_m": 5.0,
"options": options,
}
table = build_table([structure], {}, {5.0: "both_fill"}, None, 0.2)
# 저장 제원을 그대로 되돌려 싣는 칸(`options`)은 뺌 — 값이 **표에 닿았는지**만 봄.
for row in table["structures"]:
row.pop("options", None)
return json.dumps(table, ensure_ascii=False, sort_keys=True, default=str)
def _probe_values(option) -> list:
if option.choices:
return list(option.choices)
return [0.73, 1.37] if option.input == "number" else ["x"]
@pytest.mark.parametrize("type_id", sorted(MARKED))
def test_등록부에_표시가_있다(type_id: str) -> None:
options = {option.key: option for option in structure_type_map()[type_id].options}
for key in MARKED[type_id][1]:
note = options[key].not_in_table
assert note and "아직 표에 안 쓰임" in note, f"{type_id}.{key}"
@pytest.mark.parametrize("type_id", sorted(MARKED))
def test_표시한_칸은_정말_안_읽힌다(type_id: str) -> None:
base, keys = MARKED[type_id]
options = {option.key: option for option in structure_type_map()[type_id].options}
reference = _snapshot(type_id, dict(base))
assert '"components": []' not in reference, "기준 제원으로 표가 안 섬 — 시험이 무의미"
for key in keys:
for value in _probe_values(options[key]):
assert _snapshot(type_id, {**base, key: value}) == reference, (
f"{type_id}.{key}={value!r} 로 표가 바뀜 — 이제 읽힘, 표시를 걷을 것"
)
def test_폼_칸_이름에_붙는다() -> None:
assert "not_in_table" in FIELDS and "not_in_table" in PANEL