"""측점 없는 구조물 알림 — 조용히 빠지던 것을 드러낸다 (계획서 3-14 ㉯, 2026-09-09). 관을 나중에 놓거나 옮기면 그 측점이 안 생긴다 — 측점을 만드는 자리가 B05 노선 [확정] 한 곳뿐이기 때문이다. 그 관은 횡단도에도 안 서고 수량·금액에서 통째로 빠진다. """ from __future__ import annotations import json 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 B05_Profile.B05_Profile_Router_Confirm import ( # noqa: E402 load_sampling_snapshot, sampling_snapshot_path, ) from B06_Section.B06_Section_Router_Stations import ( # noqa: E402 STATION_MATCH_TOLERANCE_M, _station_chainages, router, ) def test_두_길이_다_열려_있다() -> None: """점검(GET)과 만들기(POST)가 같은 주소에 선다 — 화면이 하나만 알면 된다.""" paths = {(route.path, tuple(sorted(route.methods))) for route in router.routes} assert ("/api/projects/{project_id}/section/missing-stations", ("GET",)) in paths assert ("/api/projects/{project_id}/section/missing-stations", ("POST",)) in paths def test_종단_정본에서_측점을_읽는다(tmp_path: Path) -> None: folder = tmp_path / "B06_Section" / "longitudinal" folder.mkdir(parents=True) (folder / "longitudinal.json").write_text( json.dumps({"stations": [{"chainage_m": 0.0}, {"chainage_m": 85.05}, {"bad": 1}]}), encoding="utf-8", ) assert _station_chainages(tmp_path) == [0.0, 85.05] def test_측점이_없으면_빈_목록(tmp_path: Path) -> None: """파일이 없다고 터지지 않는다 — 이 줄은 덤이라 화면을 막으면 안 된다.""" assert _station_chainages(tmp_path) == [] def test_같은_자리_판정은_측점_스냅_폭() -> None: """측점 생성 스냅 폭(0.005m · 같은 횡단 이름)과 같음 — 0.5m 면 0.1m 옮긴 관을 놓침(192-1).""" assert STATION_MATCH_TOLERANCE_M == 0.005 def test_샘플링_조건이_없으면_None(tmp_path: Path) -> None: """조건을 지어내지 않는다 — 그 측점만 다른 지표에서 뽑히면 지반고가 어긋난다.""" assert load_sampling_snapshot(tmp_path) is None path = sampling_snapshot_path(tmp_path) path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps({"filter_key": "", "method": "dtm"}), encoding="utf-8") assert load_sampling_snapshot(tmp_path) is None path.write_text( json.dumps({"filter_key": "csf", "method": "tin", "smooth": True}), encoding="utf-8" ) snapshot = load_sampling_snapshot(tmp_path) assert snapshot is not None and snapshot["method"] == "tin" and snapshot["smooth"] is True