"""728-1 지킴 — SK 단위 바꿈 환산 짝: `master_unit.swap` ↔ `A00_Common/master_unit_swap.ts` `swapUnit` 거울. 같은 성격 = 배 자동 · 부피 ↔ 무게 = 단위중량 · 그 밖 = 사용자 계수 · 계수 없으면 배 없음 + 까닭 글. """ from __future__ import annotations import json import subprocess import sys from decimal import Decimal from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] HERE = Path(__file__).resolve().parent sys.path.insert(0, str(ROOT / "resources/master_data/scripts")) import master_unit as mu # noqa: E402 CASES = [ ["100본", "본", None, None], ["10㎡", "㎡", None, None], ["1,000본", "100본", None, None], ["㎡", "10㎡", None, None], ["m", "km", None, None], ["kg", "톤", None, None], ["본", "개", None, None], ["m3", "㎥", None, None], ["㎥", "㎥", None, None], ["식", "식", None, None], ["", "본", None, None], ["㎥", "m", None, None], ["㎥", "m", None, 2.5], ["㎥", "m", None, -1], ["100m", "㎡", None, 0.5], ["㎥", "톤", None, None], ["㎥", "톤", 1600, None], ["톤", "㎥", 1600, None], ["10㎥", "kg", 2400, None], ["조", "개", None, None], ["hr", "시간", None, None], # 746-1 별칭 ["개소", "개", None, None], ["10개소", "개", None, None], ] def _py(case) -> dict: got = mu.swap(*case) num = lambda x: None if x is None else float(x) # noqa: E731 return { **got, "가": [num(got["가"][0]), got["가"][1]], "나": [num(got["나"][0]), got["나"][1]], "배": num(got["배"]), } @pytest.fixture(scope="module") def ts() -> list[dict]: proc = subprocess.run( # noqa: S603 — 고정 실행 파일 ["node", str(HERE / "helper_728_1_unit_swap.cjs")], input=json.dumps(CASES), capture_output=True, text=True, encoding="utf-8", timeout=60, ) assert proc.returncode == 0, proc.stderr return json.loads(proc.stdout) def test_거울_파이썬과_TS_같은_답(ts) -> None: for case, t in zip(CASES, ts, strict=True): p = _py(case) assert (t["가"], t["나"], t["성격"], t["계수"], t["근거"]) == ( p["가"], p["나"], p["성격"], p["계수"], p["근거"], ), case assert (t["배"] is None) == (p["배"] is None), case if p["배"] is not None: assert t["배"] == pytest.approx(p["배"], rel=1e-12), case def test_같은_성격은_배_자동() -> None: assert mu.swap("100본", "본")["배"] == 100 # 단목베기 100본 당 153,889.4 → 본 당 1,538.894 assert Decimal("153889.4") / mu.swap("100본", "본")["배"] == Decimal("1538.894") assert Decimal("447913.20") / mu.swap("10㎡", "㎡")["배"] == Decimal("44791.32") assert mu.swap("100본", "본")["근거"] == "100본 당 → 본 당 ÷100" assert mu.swap("m", "km")["근거"] == "m 당 → km 당 ×1000" assert mu.swap("본", "개")["계수"] is None and mu.swap("본", "개")["근거"] == "본 = 개" assert mu.split("1,000본") == (Decimal(1000), "본") and mu.split("㎥") == (Decimal(1), "㎥") def test_다른_성격은_계수_없으면_셈_막음() -> None: got = mu.swap("㎥", "m") assert got["배"] is None and got["계수"] == "사용자" and "환산 계수" in got["근거"] assert mu.swap("㎥", "m", coef=2.5)["배"] == Decimal("2.5") assert mu.swap("㎥", "m", coef=0)["배"] is None # 0 · 음수 = 계수 없음 got = mu.swap("㎥", "톤") assert got["배"] is None and got["계수"] == "단위중량" and "CC000337" in got["근거"] assert mu.swap("㎥", "톤", density=1600)["배"] == Decimal("1.6") assert mu.swap("조", "개")["계수"] == "사용자" # 한 조 = 여럿 — 묶음 밖 def test_TS_는_새_정규식_없이_모듈_한_벌() -> None: src = (ROOT / "A00_Common/master_unit_swap.ts").read_text(encoding="utf-8") assert "master_unit.py" in src and "test_728_1_unit_swap.py" in src py = (ROOT / "resources/master_data/scripts/master_unit.py").read_text(encoding="utf-8") assert "master_unit_swap.ts" in py and "test_728_1_unit_swap.py" in py for kind, group in mu.UNITS.items(): # 단위 표가 두 파일에 같게 for u, n in group.items(): assert f"{u}: {n}" in src or f'"{u}": {n}' in src, (kind, u)