⚠ **뿌리** — `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>
176 lines
6.9 KiB
Python
176 lines
6.9 KiB
Python
"""마이그레이션 테스트 — 서버 저장 형식(구조물 문자열만)과 클라이언트 형식 모두 커버.
|
|
|
|
크로스체크 지적 1(2026-08-16): 확정 저장분은 `{chainage_m, structure}` 문자열뿐이다
|
|
(`B05_Profile_UI_Page.ts` confirmRoute 전송부). structureType이 없어도 문자열에서
|
|
종류를 알아내야 한다.
|
|
|
|
2026-09-01 사용자 확정: 정본이 갈린 타입(기슭막이 = `managed_by: pipe_points`)은
|
|
구조물 목록이 아니라 관 지점 정본으로 간다. 결과도 두 갈래(`MigrationPlan`)다.
|
|
"""
|
|
|
|
from B05_Profile.B05_Profile_Structures_Migration import migrate_irregular_stations
|
|
|
|
# ── 서버 저장 형식 (structure 문자열만) ──────────────────────────────────────
|
|
|
|
|
|
def test_server_format_gisungmagi_maps_to_revetment():
|
|
(item,) = migrate_irregular_stations(
|
|
[{"chainage_m": 120.0, "structure": "기성막이"}]
|
|
).pipe_facilities
|
|
assert item.facility == "revetment"
|
|
|
|
|
|
def test_server_format_escape_route_maps_to_refuge_with_width():
|
|
(item,) = migrate_irregular_stations(
|
|
[{"chainage_m": 300.0, "structure": "대피로 2.5m"}]
|
|
).structures
|
|
assert item.type_id == "refuge"
|
|
assert item.options["width_m"] == 2.5
|
|
|
|
|
|
def test_server_format_pipe_label_is_skipped():
|
|
"""배관 라벨(관종 D직경)은 관 정본 소관 — 옮기지 않는다."""
|
|
for label in ("파형강관 D800", "흄관 D1000", "배관"):
|
|
plan = migrate_irregular_stations([{"chainage_m": 50.0, "structure": label}])
|
|
assert plan.structures == [] and plan.pipe_facilities == []
|
|
|
|
|
|
def test_server_format_unknown_text_becomes_etc():
|
|
(item,) = migrate_irregular_stations(
|
|
[{"chainage_m": 15.0, "structure": "돌망태 보강"}]
|
|
).structures
|
|
assert item.type_id == "etc"
|
|
assert item.options["name"] == "돌망태 보강"
|
|
|
|
|
|
# ── 클라이언트 형식 (structureType 포함) ────────────────────────────────────
|
|
|
|
|
|
def test_client_format_pipe_entries_are_skipped():
|
|
plan = migrate_irregular_stations(
|
|
[
|
|
{"chainage_m": 50.0, "structure": "파형강관 D800", "structureType": "배관"},
|
|
{"chainage_m": 60.0, "structure": "배관", "origin": "pipe"},
|
|
]
|
|
)
|
|
assert plan.structures == [] and plan.pipe_facilities == []
|
|
|
|
|
|
def test_client_format_gisungmagi_maps_to_revetment():
|
|
"""기슭막이는 관 시설 — 구간·제원은 레지스트리 기본값을 승계한다(2026-09-01)."""
|
|
plan = migrate_irregular_stations(
|
|
[{"chainage_m": 120.0, "structure": "기성막이", "structureType": "기성막이"}]
|
|
)
|
|
assert plan.structures == []
|
|
(item,) = plan.pipe_facilities
|
|
assert item.facility == "revetment"
|
|
assert item.chainage_m == 120.0
|
|
# 기준측점 전/후 5m — 레지스트리 기본값.
|
|
assert (item.start_m, item.end_m) == (115.0, 125.0)
|
|
assert item.options["form"] == "돌쌓기(메)"
|
|
assert item.options["height_m"] == 2.5 and item.options["length_m"] == 10
|
|
|
|
|
|
def test_client_format_escape_route_width_field_wins():
|
|
(item,) = migrate_irregular_stations(
|
|
[
|
|
{
|
|
"chainage_m": 300.0,
|
|
"structure": "대피로 2.5m",
|
|
"structureType": "대피로",
|
|
"escapeWidthM": 3.0,
|
|
}
|
|
]
|
|
).structures
|
|
assert item.type_id == "refuge"
|
|
assert item.options["width_m"] == 3.0 # 명시 필드가 라벨 파싱보다 우선
|
|
|
|
|
|
def test_etc_keeps_custom_name():
|
|
(item,) = migrate_irregular_stations(
|
|
[
|
|
{
|
|
"chainage_m": 80.0,
|
|
"structure": "임시 표지",
|
|
"structureType": "기타",
|
|
"customName": "임시 표지",
|
|
}
|
|
]
|
|
).structures
|
|
assert item.type_id == "etc"
|
|
assert item.options["name"] == "임시 표지"
|
|
|
|
|
|
def test_duplicate_positions_are_deduplicated():
|
|
entries = [
|
|
{"chainage_m": 100.0, "structure": "기성막이"},
|
|
{"chainage_m": 100.0, "structure": "기성막이"},
|
|
]
|
|
assert len(migrate_irregular_stations(entries).pipe_facilities) == 1
|
|
|
|
|
|
def test_migration_is_idempotent():
|
|
entries = [
|
|
{"chainage_m": 10.0, "structure": "기성막이"},
|
|
{"chainage_m": 20.0, "structure": "대피로 2.0m"},
|
|
]
|
|
first = migrate_irregular_stations(entries)
|
|
second = migrate_irregular_stations(entries)
|
|
assert [(i.type_id, i.start_m) for i in first.structures] == [
|
|
(i.type_id, i.start_m) for i in second.structures
|
|
]
|
|
assert [(p.facility, p.start_m) for p in first.pipe_facilities] == [
|
|
(p.facility, p.start_m) for p in second.pipe_facilities
|
|
]
|
|
|
|
|
|
def test_empty_input_returns_empty():
|
|
plan = migrate_irregular_stations([])
|
|
assert plan.structures == [] and plan.pipe_facilities == []
|
|
|
|
|
|
# ── 다른 정본이 관리하는 A군 라벨 (2026-08-28) ──────────────────────────────
|
|
|
|
|
|
def test_group_a_labels_from_server_are_not_re_migrated():
|
|
"""서버가 종단 정본에 심는 A군 라벨은 구조물로 옮기지 않는다.
|
|
|
|
옮기면 정본이 이중화되어 "기타" 고스트가 쌓인다 — 실증: 초기화 전 프로젝트의
|
|
structures.json에 `etc@149.73`(세월교)·`etc@200.92`(BOX암거)가 남아 있었다.
|
|
"""
|
|
entries = [
|
|
{"chainage_m": 149.73, "structure": "세월교"},
|
|
{"chainage_m": 200.92, "structure": "BOX암거"},
|
|
{"chainage_m": 210.0, "structure": "물넘이포장"},
|
|
{"chainage_m": 30.0, "structure": "배수관"},
|
|
{"chainage_m": 60.0, "structure": "노출형 횡단수로"},
|
|
{"chainage_m": 70.0, "structure": "개거(겉도랑)"},
|
|
]
|
|
plan = migrate_irregular_stations(entries)
|
|
assert plan.structures == [] and plan.pipe_facilities == []
|
|
|
|
|
|
def test_pipe_owned_label_is_not_re_migrated():
|
|
"""관 시설에서 투영된 "기슭막이" 라벨은 되옮기지 않는다 — 되옮기면 "기타"로 굳는다.
|
|
|
|
구 이름("기성막이")만 이관 대상이다(2026-08-28 이관 뒤 라벨이 갈렸다).
|
|
"""
|
|
plan = migrate_irregular_stations([{"chainage_m": 120.0, "structure": "기슭막이"}])
|
|
assert plan.structures == [] and plan.pipe_facilities == []
|
|
|
|
|
|
def test_non_group_a_labels_still_migrate():
|
|
"""대조군 — 필터가 과하게 넓어지면 이 세 건이 함께 사라진다."""
|
|
(revetment,) = migrate_irregular_stations(
|
|
[{"chainage_m": 120.0, "structure": "기성막이"}]
|
|
).pipe_facilities
|
|
assert revetment.facility == "revetment"
|
|
(refuge,) = migrate_irregular_stations(
|
|
[{"chainage_m": 300.0, "structure": "대피로 2.0m"}]
|
|
).structures
|
|
assert refuge.type_id == "refuge"
|
|
(etc,) = migrate_irregular_stations(
|
|
[{"chainage_m": 15.0, "structure": "돌망태 보강"}]
|
|
).structures
|
|
assert etc.type_id == "etc"
|