Files
Aislo/resources/tester/test_excavation_mirror.py
eomsangdonandClaude Opus 5 0ef32b5279 chore(tester): 시험을 resources/tester/ 로 옮김 — 창끼리 건너가게
⚠ **뿌리** — `tmp/` 는 창 사이에 안 건너감(실측 확인: 상대 창이 놓은 `tmp/_sync_probe.txt`
가 시간을 두고 두 번 봐도 안 보임). 그래서 **정본(등록부 스키마)만 건너가고 그것을 읽는
시험은 안 건너가** 오늘 두 번, 같은 시험이 **연 창은 통과·받은 창은 실패**가 됐음.

- `tmp/tests/*` 를 `resources/tester/` 로 **복사**(127 파일). 내용은 **한 줄도 안 고침**
- `tmp/tests` 는 **남겨 둠** — 되돌릴 자리(사용자 지시)
- 실행: `./venv/Scripts/python.exe -m pytest resources/tester/ -q`
  옮기기 전과 **같은 수**: 617 통과 / 22 건너뜀 / 실패 0

⇒ 이제 시험·예외·까닭이 **정본과 함께** 움직임. 오늘 세운 「예외는 정본 스키마에」와 짝임.

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

142 lines
4.9 KiB
Python

"""터파기 단면 — 파이썬·TS 짝이 같은 값을 내는지 (2026-09-09).
화면(B06 횡단도)이 그리고 서버(B08 수량)가 세는 값이라 두 쪽이 갈리면
「그림은 이런데 수량은 저렇다」가 된다.
⚠ 근거의 급이 다른 두 갈래를 함께 잠근다 —
관은 **법정 표**(KCS 44 40 10 그림 3.2-1), 벽은 **실무 정본 식**(구조도 기슭막이 xls).
"""
from __future__ import annotations
import json
import re
import subprocess
import sys
from pathlib import Path
import pytest
PROJECT_ROOT = Path(__file__).resolve().parents[2]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
from common_util.common_util_excavation import ( # noqa: E402
PIPE_TRENCH_WIDTH_MM,
WALL_FOUNDATION_DEPTH_M,
WALL_FOUNDATION_WIDTH_M,
WALL_TRENCH_CLEARANCE_M,
pipe_trench_width_m,
wall_trench_area_m2,
wall_trench_width_m,
)
TSC = PROJECT_ROOT / "config" / "node_modules" / "typescript" / "bin" / "tsc"
_RUNNER = """
import { writeFileSync } from "node:fs";
import {
PIPE_TRENCH_WIDTH_MM,
pipeTrenchWidthM,
wallTrenchAreaM2,
wallTrenchWidthM,
} from "./common_util_excavation.js";
const out = {
table: PIPE_TRENCH_WIDTH_MM,
pipe: [300, 800, 1000, 1200, 1500, 250, 1600].map((d) => pipeTrenchWidthM(d)),
wallWithFoundation: [1.0, 2.0, 3.0].map((h) => wallTrenchAreaM2(h, 0.7, true)),
wallBlindingOnly: [1.0, 2.0, 3.0].map((h) => wallTrenchAreaM2(h, 0.7, false)),
wallWidth: [0.7, 1.05, 0].map((t) => wallTrenchWidthM(t)),
nulls: [pipeTrenchWidthM(null), wallTrenchAreaM2(null, 0.7, true), wallTrenchAreaM2(1, null, true)],
};
writeFileSync(process.argv[2], JSON.stringify(out));
"""
def _ts_values(tmp_path: Path) -> dict:
out = tmp_path / "js"
subprocess.run( # noqa: S603 — 고정 실행 파일
[
"node",
str(TSC),
str(PROJECT_ROOT / "common_util" / "common_util_excavation.ts"),
"--outDir",
str(out),
"--module",
"esnext",
"--target",
"es2022",
"--moduleResolution",
"bundler",
"--ignoreConfig",
],
cwd=str(PROJECT_ROOT),
check=True,
capture_output=True,
)
for emitted in out.glob("*.js"):
text = emitted.read_text(encoding="utf-8")
emitted.write_text(
re.sub(r'(from "\./[^"]+?)(")', lambda m: m.group(1) + ".js" + m.group(2), text),
encoding="utf-8",
)
(out / "runner.mjs").write_text(_RUNNER, encoding="utf-8")
result = tmp_path / "out.json"
subprocess.run( # noqa: S603
["node", str(out / "runner.mjs"), str(result)],
cwd=str(PROJECT_ROOT),
check=True,
capture_output=True,
)
return json.loads(result.read_text(encoding="utf-8"))
@pytest.mark.skipif(not TSC.is_file(), reason="프론트엔드 의존성 미설치")
def test_두_쪽이_같은_값을_낸다(tmp_path: Path) -> None:
ts = _ts_values(tmp_path)
assert {int(k): v for k, v in ts["table"].items()} == PIPE_TRENCH_WIDTH_MM
assert ts["pipe"] == [pipe_trench_width_m(d) for d in (300, 800, 1000, 1200, 1500, 250, 1600)]
assert ts["wallWithFoundation"] == [
wall_trench_area_m2(h, 0.7, has_foundation=True) for h in (1.0, 2.0, 3.0)
]
assert ts["wallBlindingOnly"] == [
wall_trench_area_m2(h, 0.7, has_foundation=False) for h in (1.0, 2.0, 3.0)
]
assert ts["wallWidth"] == [wall_trench_width_m(t) for t in (0.7, 1.05, 0)]
assert ts["nulls"] == [None, None, None]
def test_관은_표를_그대로_쓴다() -> None:
"""⚠ 관경 + 2b 로 계산하지 않는다 — 표가 관 두께·작업여유를 담고 있다."""
assert pipe_trench_width_m(800) == 1.6
assert pipe_trench_width_m(800) != 0.8 + 2 * 0.3
for diameter in (800, 1000, 1200, 1500):
assert pipe_trench_width_m(diameter) is not None, diameter
def test_표에_없는_관경은_지어내지_않는다() -> None:
assert pipe_trench_width_m(250) is None
assert pipe_trench_width_m(1600) is None
def test_실무_정본_수치와_맞는다() -> None:
"""xls 7탭: H=1.0 → 1.03+0.45 = 1.48 · H=2.0 → 2.51 · H=3.0 → 3.54 (평균두께 0.83)."""
thickness = 0.83
for height, expected in ((1.0, 1.48), (2.0, 2.51), (3.0, 3.54)):
area = wall_trench_area_m2(height, thickness, has_foundation=True)
assert area == pytest.approx(expected, abs=0.01), height
def test_기초_유무가_기초분을_가른다() -> None:
with_base = wall_trench_area_m2(2.0, 0.7, has_foundation=True)
without = wall_trench_area_m2(2.0, 0.7, has_foundation=False)
assert with_base - without == pytest.approx(
WALL_FOUNDATION_DEPTH_M * WALL_FOUNDATION_WIDTH_M - 0.1 * 0.7
)
def test_여유폭은_평균두께에_더한다() -> None:
assert wall_trench_width_m(0.7) == pytest.approx(0.7 + WALL_TRENCH_CLEARANCE_M)