Files
Aislo/resources/tester/test_b06_recompute_keeps_user_values.py
T
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

110 lines
4.4 KiB
Python

"""포장 구간 재계산이 **사용자 값을 지우지 않는지**.
왜 (실사고 `b6941bd2`) — 포장 구간·세월교 측점은 저장 때 서버가 횡단을 **다시 계산해
통째로 갈아 끼운다**. 계산이 만들지 않는 값(구조물 조정·다단 구간값 등)은 그 자리에서
따로 베껴 넣어야 살아남는데, `extra_spans` 가 목록에서 빠져 조용히 사라졌다.
이 시험이 보는 것은 **베껴 넣는 그 자리**다. 지형·계획고는 시험 대상이 아니므로 가짜로
바꿔 끼운다(그 둘은 각자 시험이 있다). 목록 자체가 갈리는 것은
`test_b06_user_touched_keys.py`, 새 사용자 값이 목록에서 새는 것은
`test_b06_design_key_split.py` 가 지킨다.
"""
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 import B06_Section_Router_Design as design_mod # noqa: E402
USER_VALUES = {
"display_half_width_m": 12.5,
"inlet_structure": "L",
"basin_adjust": {"innerWidthM": 1.5, "innerHeightM": 1.5, "lateralM": 0.5, "slopeM": 0.2},
"revet_adjust": {"outlet": {"x": 2.0, "d": 0.5, "h": None, "m": None}},
"ford_adjust": {"inlet": {"heightM": None, "lateralM": 1.0, "slopeM": 0.0}},
"box_adjust": {"left": {"lengthM": 2.0, "riseM": 0.0}},
"extra_wall_counts": {"outlet": 2, "basin": 0},
"extra_spans": {"extra0": {"length_m": 15.0, "before_m": 8.0, "after_m": 7.0}},
"revet_link_detached": True,
"revet_follow_grade": False,
}
#: 재계산 인자로 되먹여 살아남는 갈래 — 결과에 그대로 나와야 한다.
FED_BACK = {
"ground_type": "soil",
"section_mode": "right_cut",
"ditch_side": "left",
"ditch_type": "l_type",
"two_stage_slope": False,
"rock_boundary_offset_m": -1.5,
}
def _section() -> dict:
design = {
"paved": False,
"status": "ok",
"pavement_suggested": True,
**USER_VALUES,
**FED_BACK,
}
return {"chainage_m": 100.0, "samples": [], "design": design}
def _install_fakes(monkeypatch) -> dict:
"""지형·계획고·포장구간을 가짜로 — 이 시험의 대상은 「값을 베껴 넣는 자리」다."""
seen: dict = {}
def fake_compute(samples, elevation, **kwargs):
seen.update(kwargs)
# 계산이 내는 값만 담은 새 설계 — 사용자 값은 하나도 없다(실제 엔진과 같다).
return {
"paved": True,
"cut_area_m2": 1.0,
"fill_area_m2": 2.0,
**{
key: kwargs[key]
for key in (
"ground_type",
"section_mode",
"ditch_side",
"ditch_type",
"two_stage_slope",
"rock_boundary_offset_m",
)
if key in kwargs
},
}
monkeypatch.setattr(design_mod, "pavement_ranges", lambda root: [(0.0, 200.0)])
monkeypatch.setattr(design_mod, "compute_cross_design", fake_compute)
monkeypatch.setattr(design_mod, "design_elevation_from_longitudinal", lambda lon, ch: 100.0)
monkeypatch.setattr(design_mod, "curve_widening_args", lambda section: {})
return seen
def test_포장_재계산_뒤에도_사용자_값이_남는다(monkeypatch):
_install_fakes(monkeypatch)
sections = [_section()]
changed = design_mod.enforce_pavement_ranges({}, sections, Path("."), None)
assert changed == 1, "재계산이 아예 안 돌았음 — 시험 전제가 깨짐"
result = sections[0]["design"]
for key, value in USER_VALUES.items():
assert result.get(key) == value, f"{key} 가 재계산에서 사라짐"
assert result["status"] == "ok"
assert result["pavement_suggested"] is True
assert result["paved"] is True, "포장 구간인데 포장으로 안 바뀜"
def test_되먹임_값이_인자로_실제로_들어간다(monkeypatch):
"""①갈래는 「인자로 넣어」 지킨다 — 안 넣으면 기본값으로 되돌아간다."""
seen = _install_fakes(monkeypatch)
sections = [_section()]
design_mod.enforce_pavement_ranges({}, sections, Path("."), None)
for key, value in FED_BACK.items():
assert seen.get(key) == value, f"{key} 가 재계산 인자로 안 들어감(넘긴 값: {seen.get(key)})"
assert seen.get("paved") is True, "포장 구간 재계산은 포장으로 켜야 함"