Files
Aislo/resources/tester/test_800_2_equation_layout.py
eomsangdonandClaude Opus 5.5 7480aebc96 feat(804-6): 옛 수식 탭 걷음 · 줄 쌓기 = 첫 「수식」 탭(요구 686-1)
- M01 단가산출 기초 · M02 단가산출 상세 보기 = 수식(줄 쌓기 · 기본) · 단가산출 상세 둘
- 줄 쌓기에 M02 사본 [단가 갱신] · [재생성](미리 셈 → 알림 → 저장 · 고침 있으면 막음) · 판 바뀜(409) 문서 그대로면 새 판으로 다시 저장 옮김
- 옛 수식 문서 화면 걷음(formula_doc_screen · defs · edit · lines · math · math_model · rows · sub · formula_doc.css) · 이미 안 부르던 796-2 수식 나무 화면(LogicLab_Equation · Defs · Var · css · M01_Logic_Equation_Model · sheet_formula_cell · ui_template_equation_defs · edit) 걷음 — 18 파일 4,860 줄
- formula_doc_render = 줄 쌓기가 쓰는 reach 만 · 옵션 가로 CSS 는 line_stack.css 로
- 남김 = 계산기 common_util_formula_doc* · 서버 길 · 옵션 · 사본 표지 · 합계 상자 · KaTeX · 시험 페이지 tools/line-stack-test
- 시험: test_796_2 지움(걷은 화면 원본 검사뿐) · 799_1 · 800_2 걷은 화면 줄만 뺌 · 799_2 · 802_4b2 · 804_2 보기 · 화면 파일 대상 바꿈 · test_804_6 새로(걷은 파일 · 부르는 곳 없음 · 첫 탭 · 사본 할일)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 11:09:44 +09:00

128 lines
5.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""PLAN 800-2 · 800-3 — 수식 탭 변수 정의 영역 · 바로 고침 · 새 기호 연결 (서버 몫 · 임시 쓰기 없음)."""
import json
import re
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path[:0] = [str(ROOT), str(ROOT / "resources/master_data/scripts")]
from M01_MasterData import M01_MasterData_Equation as eq # noqa: E402
from M01_MasterData import M01_MasterData_Store as store # noqa: E402
KEY = "GC000211"
OFF = {"폼타이": "아님", "측압": "3t/㎡"}
ON = {"폼타이": "사용", "측압": "4t/㎡"}
def _defs(inputs):
return eq.read(KEY, inputs)["수식"]["정의"]
def _text(defs):
return json.dumps(defs, ensure_ascii=False)
def test_defs_merge_and_clean():
defs = _defs(OFF)
signs = [(d["기호"], d["위"], d["아래"]) for d in defs]
assert len(signs) == len(set(signs)), "같은 변수는 한 번만"
assert not re.search(r"[A-Z]{2}\d{6}", _text(defs)), "DB 열쇠 글 0"
assert all(
set(d) <= {"열쇠", "기호", "위", "아래", "이름", "갈래", "연결", "고침", "안씀"}
for d in defs
)
by = {
(d["이름"], d["갈래"]): d for d in defs
} # 800-1 기호가 생겨 중간 · 표 찾기는 다른 기호 = 다른 정의
sign = lambda d: (d["기호"], d["위"], d["아래"])
assert sign(by[("보통인부", "중간")]) != sign(by[("보통인부", "찾기")])
assert by[("사용횟수", "입력")]["연결"] == ["입력 — 옵션에서 고름"]
def test_unpicked_branches_hidden():
off, on = _text(_defs(OFF)), _text(_defs(ON))
for col in ("4t/㎡", "5t/㎡", "6t/㎡", "폼타이 소요량"):
assert col not in off
assert "칸 4t/㎡" in on and "칸 3t/㎡" not in on and "칸 5t/㎡" not in on
assert "측압" in on and "측압" not in off # 폼타이 아님이면 측압 갈래도 안 탐
def test_live_edit_preview_changes_total():
spot = {"할일": "식", "자리": "호표:0", "식": "형틀목공 × 2"}
got = eq.preview(KEY, [spot], OFF)
assert got["되나"] and got["후"]["계"] > got["전"]["계"]
def test_unknown_symbol_asks_link_then_links():
spot = {"할일": "식", "자리": "호표:0", "식": "형틀목공 × 2 + Z"}
got = eq.preview(KEY, [spot], OFF)
assert not got["되나"] and "모르는 기호 「Z」" in got["까닭"][0]
for link in (
{"갈래": "상수", "값": "0"},
{"갈래": "입력", "기본값": "0"},
{"갈래": "표", "표": "QC000431", "칸": "형틀목공", "조건": {"유형": "유형"}},
{"갈래": "요소", "요소": "LB000007"},
):
add = {"할일": "연결", "열쇠": "Z", "이름": "새값", **link}
got = eq.preview(KEY, [add, spot], OFF)
assert got["되나"], (link, got["까닭"])
assert any(d["기호"] == "Z" for d in got["수식"]["정의"])
def test_link_bad_input_blocked():
bad = [
{"갈래": "표", "표": "QC000431", "칸": "없는칸", "조건": {"유형": "유형"}},
{"갈래": "표", "표": "QC000431", "칸": "형틀목공", "조건": {}},
{"갈래": "요소", "요소": "GC000211"},
{"갈래": "상수", "값": "abc"},
]
for link in bad:
got = eq.preview(KEY, [{"할일": "연결", "열쇠": "Z", **link}], OFF)
assert not got["되나"], link
def test_drop_guard_and_unused_input():
got = eq.preview(KEY, [{"할일": "지움", "열쇠": "사용횟수"}], OFF)
assert not got["되나"] and "쓰는 곳" in got["까닭"][0]
add = {"할일": "연결", "열쇠": "Y", "갈래": "입력"}
got = eq.preview(KEY, [add], OFF)
unused = [d for d in got["수식"]["정의"] if d["기호"] == "Y"]
assert unused and unused[0].get("안씀")
assert eq.preview(KEY, [add, {"할일": "지움", "열쇠": "Y"}], OFF)["되나"]
def test_candidates():
whole = store.loaded()[1]
got = eq.links({"갈래": "표", "검색": "합판거푸집 폼타이", "분류": ""})
assert got["후보"] and "조건" in got["후보"][0]
assert eq.links({"갈래": "요소", "검색": "형틀목공", "분류": "인력"})["후보"]
assert eq.links({"갈래": "로직", "검색": "합판거푸집", "분류": ""})["후보"]
assert whole is not None
def test_groups_add_up_to_total():
"""800-4 — 묶음(블록 · 자원 · 덧줄) 소계 합 + 끝수 = 합계(비목마다) · 한 묶음 소계 = 노 + 재 + 경."""
for key in ("GC001148", "GC000211"):
eqn = eq.read(key, {})["수식"]
sub, total = eqn["소계"], eqn["합계"]
for k in ("노무비", "재료비", "경비"):
got = sum(float(r[k]) for r in sub["줄"]) + float(sub["끝수"][k])
assert abs(got - float(total[k])) < 1e-6, (key, k)
assert all(
abs(float(r["계"]) - sum(float(r[k]) for k in ("노무비", "재료비", "경비"))) < 1e-6
for r in sub["줄"]
)
def test_screen_source_groups_and_inline_edit():
ui = ROOT / "ui_template"
sum_ts = (ui / "ui_template_equation_sum.ts").read_text(encoding="utf-8")
line_ts = (ui / "ui_template_equation_line.ts").read_text(encoding="utf-8")
assert "ORDER" in sum_ts and "ui-eq__grp" in sum_ts # 가 · 나 · 다 묶음
assert "o.after?.(line)" in line_ts # 블록 식 줄 바로 아래
assert "block-key" not in line_ts # 줄 곁 DB 열쇠 글 없음
assert "ui-eq__solve" not in line_ts and "ui-eq__step" not in line_ts # 풀이 · 줄 번호 걷음