⚠ **뿌리** — `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>
75 lines
3.1 KiB
Python
75 lines
3.1 KiB
Python
"""B05 횡단배수 최소 계획고 규칙 — TS 산식이 지식DB·엔진 상수와 맞는지 대조.
|
||
|
||
TS 구현(`B05_Profile_UI_Profile_MinCover.ts`)의 산식은
|
||
배수관: 지반고 + 관경(m) + 토피 0.5
|
||
BOX암거: 지반고 + 구체 높이(m) + 토피 0.5
|
||
이다(2026-08-23 사용자 확정). 여기서는 그 상수·기본값이 코드에 그대로 있는지와
|
||
B06 배수관 엔진의 토피 상수와 같은 값인지 확인한다 — 두 화면이 다른 토피를 쓰면
|
||
종단에서 통과한 계획선이 횡단에서 성립하지 않는다.
|
||
"""
|
||
|
||
import re
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
PROJECT_ROOT = Path(__file__).resolve().parents[2]
|
||
if str(PROJECT_ROOT) not in sys.path:
|
||
sys.path.insert(0, str(PROJECT_ROOT))
|
||
|
||
from B06_Section.B06_Section_Engine_Culvert import MIN_PIPE_COVER_M # noqa: E402
|
||
from common_util.common_util_drainage_pipes import facility_clearance_m # noqa: E402
|
||
|
||
SOURCE = (PROJECT_ROOT / "B05_Profile" / "B05_Profile_UI_Profile_MinCover.ts").read_text(
|
||
encoding="utf-8"
|
||
)
|
||
|
||
|
||
def _const(name: str) -> float:
|
||
match = re.search(rf"{name}\s*=\s*([\d.]+)", SOURCE)
|
||
assert match, f"{name} 상수를 찾지 못했습니다"
|
||
return float(match.group(1))
|
||
|
||
|
||
def test_cover_matches_culvert_engine():
|
||
"""토피 0.5m는 B06 배수관 엔진과 같은 값이어야 한다(두 화면 일관성)."""
|
||
assert _const("MIN_COVER_M") == MIN_PIPE_COVER_M == 0.5
|
||
|
||
|
||
def test_default_sizes_match_user_examples():
|
||
"""사용자 확정 예시 기본값 — 배수관 Ø1000, BOX 2.0m."""
|
||
assert _const("DEFAULT_PIPE_DIAMETER_MM") == 1000
|
||
assert _const("DEFAULT_BOX_HEIGHT_M") == 2
|
||
|
||
|
||
def test_clearance_examples():
|
||
"""예시 그대로: Ø1000 → +1.5m, BOX 2.0×2.0 → +2.5m."""
|
||
cover = _const("MIN_COVER_M")
|
||
assert _const("DEFAULT_PIPE_DIAMETER_MM") / 1000 + cover == 1.5
|
||
assert _const("DEFAULT_BOX_HEIGHT_M") + cover == 2.5
|
||
|
||
|
||
def test_ford_bridge_is_pipe_plus_extra():
|
||
"""세월교 = 배관 다발 — 배수관 산식 + 물넘이 몫 0.5m (2026-08-23 사용자 확정)."""
|
||
assert facility_clearance_m("ford_bridge", {}) == 1.0 + MIN_PIPE_COVER_M + 0.5 == 2.0
|
||
assert facility_clearance_m("ford_bridge", {"pipe_diameter_mm": 800}) == 0.8 + 0.5 + 0.5
|
||
|
||
|
||
def test_ford_pavement_needs_no_clearance():
|
||
"""물넘이포장은 도로에 그대로 만든다 — 요구 여유 0."""
|
||
assert facility_clearance_m("ford_pavement", {}) == 0.0
|
||
assert facility_clearance_m("ford_pavement", {"ford_height_m": 0.4}) == 0.0
|
||
|
||
|
||
def test_backend_is_the_source_of_truth():
|
||
"""화면 사본과 백엔드 정본 산식이 같은 값을 내야 한다(두 화면 일관성)."""
|
||
assert facility_clearance_m("pipe", {}) == _const("DEFAULT_PIPE_DIAMETER_MM") / 1000 + _const(
|
||
"MIN_COVER_M"
|
||
)
|
||
assert facility_clearance_m("box_culvert", {}) == _const("DEFAULT_BOX_HEIGHT_M") + _const(
|
||
"MIN_COVER_M"
|
||
)
|
||
assert facility_clearance_m("ford_bridge", {}) == _const(
|
||
"DEFAULT_PIPE_DIAMETER_MM"
|
||
) / 1000 + _const("MIN_COVER_M") + _const("FORD_BRIDGE_EXTRA_M")
|
||
assert facility_clearance_m("pipe", {"pipe_diameter_mm": 600}) == 0.6 + MIN_PIPE_COVER_M
|