"""일위대가 수량 · 반영 · 합 거울 시험 — `M02_Labor_Doc.settle`(파이썬) ↔ `M02_MasterTemplete_Labor_Calc.ts` `settle`(TS · Node) 가 같은 답(CLAUDE.md 5장 ①). 기준은 서버가 한 번 셈(`calc`) · 그 답에 다른 알약 값을 넣어 둘이 같은지 봄. """ import json import os import subprocess import pytest from M02_MasterTemplete import M02_Labor_Doc as labor HERE = os.path.dirname(os.path.abspath(__file__)) TEN, THOUSAND, PLAIN, MAT = "GC000421", "GF000017", "GC000422", "MT000008" def _ts(answer: dict, doc: dict, values: dict) -> dict: proc = subprocess.run( ["node", os.path.join(HERE, "helper_m02_labor_calc.cjs")], input=json.dumps({"답": answer, "문서": doc, "값": values}, ensure_ascii=False), capture_output=True, text=True, encoding="utf-8", check=True, ) return json.loads(proc.stdout) def _same(a, b) -> None: if isinstance(a, dict): assert set(a) == set(b) for k in a: _same(a[k], b[k]) elif isinstance(a, list): assert len(a) == len(b) for x, y in zip(a, b): _same(x, y) elif isinstance(a, (int, float)) and not isinstance(a, bool): assert b == pytest.approx(a, rel=1e-9) else: assert a == b @pytest.mark.parametrize( "values", [ {}, # 수량 없음 — 반영 null · 손만 {"사석 수상고르기|㎡": 2.5, f"자재|{MAT}": "3"}, {"사석 수상고르기|㎡": "1,200", "나무식재|본": 7, f"자재|{MAT}": "글"}, # 쉼표 · 수 아님 ], ) def test_파이썬과_TS_가_같은_답(values): doc = labor.clean( { "열": "rv", "담은로직": [ {"로직": TEN, "수량": None}, {"로직": THOUSAND, "수량": {"손": 4}}, {"로직": PLAIN, "수량": None}, ], "자재": [{"코드": MAT, "수량": None}], } ) answer = labor.calc(doc, {}) keys = {line["알약"] for line in answer["줄"]} assert {"사석 수상고르기|㎡", "나무식재|본"} <= keys # 알약 키가 시험 값과 맞음 py = labor.settle(answer, doc, values) _same(py, _ts(answer, doc, values)) assert py == labor.calc(doc, values) # settle 만 다시 = 처음부터 다시