Files
eomsangdonandClaude Opus 5 d7cb14f416 test(B08): tmp/tests 중 tester 에 없던 47 개를 resources/tester 로 옮김
tmp/ 가 창끼리 안 건너가는 것이 확정돼(랩탑이 시간 두고 두 번 확인) 시험·예외가
저절로 건너가도록 git 안으로 옮김. 사용자 확정.

- 내용은 하나도 안 고침 — 자리만 옮김. tmp/tests 는 남겨 둠.
- 같은 이름이 이미 있던 64 개는 랩탑 것을 그대로 두고 건너뜀.
- helper_b05_*.js 둘은 랩탑이 .cjs 로 이미 올린 것과 **줄바꿈만 다른 같은 내용**이라
  복사본을 도로 뺌(시험이 .cjs 를 부름).
- resources/tester/ 에서 전체 1176 통과 · 29 건너뜀 · 실패 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-09 17:15:57 +09:00

108 lines
4.0 KiB
Python

"""사용자에게 뜨는 문구 검사 — **키 이름이 화면에 새지 않는다** (B08 ㉑).
⚠ 「`back_len_cm` 가 저장돼 있지 않아 갈래를 못 고름」처럼 개발자 키가 그대로 뜨던 자리가
있었다. 사용자는 그 이름을 모르고 무엇을 해야 하는지도 알 수 없다.
⚠ 「없다」만 말하지 않는다 — **어디서 채우면 풀리는지**까지 있어야 그 말이 쓸모 있다.
"""
from __future__ import annotations
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT))
from B08_Quantity.B08_Quantity_Engine_Handoff import build_handoff, masonry_class # noqa: E402
from B08_Quantity.B08_Quantity_Engine_UnitQuantity import build_table, expand # noqa: E402
from B08_Quantity.B08_Quantity_Wording import ( # noqa: E402
OPTION_LABELS,
option_missing,
spec_missing,
type_label,
)
#: 화면 문구에 나오면 안 되는 것 — 저장 제원 키·구조물 `type_id` 같은 개발자 이름.
LEAK_PATTERN = re.compile(
r"back_len_cm|stone_cm|height_m|length_m|face_slope_ratio"
r"|masonry_wet|masonry_dry|boulder_masonry|retaining_wall|soil_guard|pipe_inlet_basin"
)
def _notes(structures: list[dict]) -> list[str]:
table = build_table(structures)
return [note for item in table["structures"] for note in item["notes"]]
def test_돌쌓기_뒷길이_안내가_사람_말일것() -> None:
kind, why = masonry_class({})
assert kind is None
assert "뒷길이" in why
assert not LEAK_PATTERN.search(why), why
# 어디서 채우면 되는지가 있어야 한다.
assert "입력" in why
def test_큰돌쌓기_직경_안내가_사람_말일것() -> None:
notes = _notes([{"type_id": "boulder_masonry", "options": {"height_m": 2.0, "length_m": 10.0}}])
assert notes and "돌 직경" in notes[0]
assert not LEAK_PATTERN.search(notes[0]), notes[0]
def test_산출식_없는_종류_안내가_사람_말일것() -> None:
notes = _notes([{"type_id": "soil_guard", "options": {"height_m": 2.0, "length_m": 10.0}}])
assert any("흙막이" in note for note in notes)
assert not any(LEAK_PATTERN.search(note) for note in notes), notes
def test_규격_미확보_안내가_사람_말일것() -> None:
result = expand(
{
"type_id": "retaining_wall",
"options": {"height_m": 1.6, "length_m": 10.0, "form": "반중력식"},
}
)
note = next(n for n in result.notes if "규격" in n)
assert "옹벽" in note and "옹벽 형식" in note
assert not LEAK_PATTERN.search(note), note
def test_인계_못이은_줄도_사람_말일것() -> None:
unit = build_table(
[
{
"type_id": "soil_guard",
"start_m": 0.0,
"end_m": 10.0,
"options": {"height_m": 2.0, "length_m": 10.0},
}
]
)
unmatched = build_handoff(unit_quantity_table=unit)["unmatched_work_items"]
assert unmatched and "흙막이" in unmatched[0]
assert not any(LEAK_PATTERN.search(item) for item in unmatched), unmatched
def test_모르는_키는_지어내지_않을것() -> None:
"""⚠ 잘못된 안내가 없는 안내보다 나쁘다 — 모르면 키를 그대로 보인다."""
text = option_missing("듣도보도못한키")
assert "듣도보도못한키" in text
def test_라벨표에_어디서_채우는지가_있을것() -> None:
for key, (label, where) in OPTION_LABELS.items():
assert label and label != key, key
assert isinstance(where, str)
def test_이름표에_없으면_원래_값을_보일것() -> None:
assert type_label("듣도보도못한종류") == "듣도보도못한종류"
assert type_label("masonry_wet") == "돌쌓기(찰)"
# 레지스트리 이름이 있으면 그것이 먼저다.
assert type_label("masonry_wet", {"masonry_wet": "돌쌓기(찰쌓기)"}) == "돌쌓기(찰쌓기)"
def test_자료가_통째로_없으면_그렇게_말할것() -> None:
assert "표준 물량 자료" in spec_missing("box_culvert", [])