⚠ **뿌리** — `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>
74 lines
3.2 KiB
Python
74 lines
3.2 KiB
Python
"""구 비정규 측점 이관은 **한 번만** — 2026-08-24 사용자 확정.
|
|
|
|
원천(종단 정본의 비정규 측점)은 원복용으로 그대로 두고, 옮긴 이력만 구조물 정본에
|
|
남긴다. 그래야 사용자가 그 구조물을 지운 뒤 B05에 다시 들어와도 되살아나지 않는다.
|
|
"""
|
|
|
|
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_Structures_Repository import ( # noqa: E402
|
|
load_migrated_legacy,
|
|
load_structures,
|
|
save_structures,
|
|
)
|
|
from B05_Profile.B05_Profile_Structures_Migration import migrate_irregular_stations # noqa: E402
|
|
|
|
|
|
def _key(item) -> str:
|
|
return f"{item.type_id}@{round(item.anchor_m(), 3)}"
|
|
|
|
|
|
def test_history_survives_plain_save(tmp_path):
|
|
"""일반 저장(구조물 편집)이 이력을 지우면 안 된다 — 지우면 삭제분이 되살아난다."""
|
|
root = str(tmp_path)
|
|
revision = save_structures(root, [], base_revision=0, migrated_legacy={"erosion_check@10.0"})
|
|
assert load_migrated_legacy(root) == {"erosion_check@10.0"}
|
|
# 이력 인자 없이 다시 저장해도 남아 있어야 한다.
|
|
save_structures(root, [], base_revision=revision)
|
|
assert load_migrated_legacy(root) == {"erosion_check@10.0"}
|
|
|
|
|
|
def test_history_accumulates(tmp_path):
|
|
"""여러 번 이관해도 이력은 합쳐진다."""
|
|
root = str(tmp_path)
|
|
revision = save_structures(root, [], base_revision=0, migrated_legacy={"a@1.0"})
|
|
save_structures(root, [], base_revision=revision, migrated_legacy={"b@2.0"})
|
|
assert load_migrated_legacy(root) == {"a@1.0", "b@2.0"}
|
|
|
|
|
|
def test_migration_candidate_keys_are_stable(tmp_path):
|
|
"""이관 후보의 표식이 저장 왕복에도 같아야 한다 — 달라지면 매번 다시 옮긴다."""
|
|
stations = [{"chainage_m": 10.0, "structure": "돌쌓기 기슭막이"}]
|
|
candidates = migrate_irregular_stations(stations).structures
|
|
if not candidates: # 매핑이 없는 문구면 이 검증은 대상 아님
|
|
return
|
|
root = str(tmp_path)
|
|
save_structures(root, candidates, base_revision=0)
|
|
_revision, stored = load_structures(root)
|
|
assert {_key(item) for item in stored} == {_key(item) for item in candidates}
|
|
|
|
|
|
def test_deleted_structure_is_not_recreated(tmp_path):
|
|
"""이관 → 삭제 → 재이관 시도: 이력에 있으므로 다시 만들지 않는다."""
|
|
stations = [{"chainage_m": 10.0, "structure": "돌쌓기 기슭막이"}]
|
|
candidates = migrate_irregular_stations(stations).structures
|
|
if not candidates:
|
|
return
|
|
root = str(tmp_path)
|
|
history = {_key(item) for item in candidates}
|
|
revision = save_structures(root, candidates, base_revision=0, migrated_legacy=history)
|
|
|
|
# 사용자가 전부 지운다(일반 저장 경로).
|
|
revision = save_structures(root, [], base_revision=revision)
|
|
assert load_structures(root)[1] == []
|
|
|
|
# 재진입 — 라우터와 같은 판정: 자리도 비었지만 이력에 있으니 후보에서 빠진다.
|
|
migrated_before = load_migrated_legacy(root)
|
|
fresh = [item for item in candidates if _key(item) not in migrated_before]
|
|
assert fresh == []
|