Files
Aislo/resources/tester/test_256_2_b08_milestone_route_image.py
T

141 lines
5.8 KiB
Python

"""256-2 B08 거리이정표 경로 그림 = 전체 경로(사용자 162-7).
캡처 · 길찾기는 가짜로:
① 사슬 = 거래처 → 기준점 사슬(254 bases · to) → 시점 · 화면 `mapMarks` 차례 · 좌표 없는 상자 뺌
② 구간마다 카카오 길 선 · 수기 · 실패 구간 = 곧은 선 · auto/<경로 id>.png
③ [저장] 뒤 지문 비교 — 안 바뀜 = 0 · 기준점 · 시점 옮김 = 그 사슬 경로만 · 안 이은 거래처 = 없음 ·
화면 [길찾기] 그림(거래처 구간만)이 들어오면 다음 [저장]에 전체로
"""
import sys
from pathlib import Path
from uuid import uuid4
from fastapi import FastAPI
from fastapi.testclient import TestClient
ROOT = Path(__file__).resolve().parents[2]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from B08_Quantity import B08_Quantity_Router_Milestone as ms # noqa: E402
PNG = b"\x89PNG\r\n\x1a\nfake-route"
START = [127.5, 35.4]
BASES = [
{"id": "b1", "name": "거창IC", "lon": 127.91, "lat": 35.68, "to": "b2"},
{"id": "b2", "name": "함양JC", "lon": 127.72, "lat": 35.52, "manual": True},
]
ROUTES = [
{"id": "r1", "name": "거창레미콘", "lon": 127.95, "lat": 35.70, "to": "b1"},
{"id": "r2", "name": "직송", "lon": 127.60, "lat": 35.45},
{"id": "r3", "name": "안 이음", "lon": 127.61, "lat": 35.46, "linked": False},
{"id": "r4", "name": "좌표 없음", "to": "b2"},
]
DATA = {"bases": BASES, "routes": ROUTES}
class Fake:
def __init__(self):
self.shots = [] # (경로 id, lines, marks)
self.asked = [] # 길찾기 구간
def shoot(self, out_dir, route_id, lines, marks):
self.shots.append((route_id, lines, marks))
out_dir.mkdir(parents=True, exist_ok=True)
(out_dir / f"{route_id}.png").write_bytes(PNG)
return {"saved": True, "reason": None}
def directions(self, origin, destination):
self.asked.append((origin.lon, destination.lon))
if origin.lon == 127.60: # r2 → 시점 = 길찾기 실패
return {"km": None, "reason": "실패"}
return {"km": 1.0, "reason": None, "path": [[origin.lat, origin.lon], [0, 0]]}
def _setup(tmp_path, monkeypatch, start=START):
fake = Fake()
box = {"start": start}
monkeypatch.setattr(ms, "make_route_image", fake.shoot)
monkeypatch.setattr(ms, "directions_km", fake.directions)
monkeypatch.setattr(ms, "make_place_image", lambda *a: {"saved": False}) # 256-1 시험
monkeypatch.setattr(
ms, "site_info", lambda root, mid: {"start_lonlat": box["start"], "mid_default_m": None}
)
return fake, box
def _save(root, data):
ms.save_data(root, ms.Milestone.model_validate(data))
ms.refresh_images(root)
def test_사슬_화면_차례():
data = ms.Milestone.model_validate(DATA).model_dump()
chain = ms.route_chain(data, data["routes"][0], START)
assert chain == [
("거창레미콘", 127.95, 35.70, False),
("거창IC", 127.91, 35.68, False),
("함양JC", 127.72, 35.52, True),
("시점", 127.5, 35.4, False),
]
assert [c[0] for c in ms.route_chain(data, data["routes"][3], START)] == ["함양JC", "시점"]
assert [c[0] for c in ms.route_chain(data, data["routes"][1], None)] == ["직송"]
def test_전체_경로_그림_구간_선(tmp_path, monkeypatch):
fake, _ = _setup(tmp_path, monkeypatch)
_save(tmp_path, DATA)
shots = {rid: (lines, marks) for rid, lines, marks in fake.shots}
assert sorted(shots) == ["r1", "r2", "r4"] # r3 안 이음 = 없음
lines, marks = shots["r1"]
assert [m["name"] for m in marks] == ["거창레미콘", "거창IC", "함양JC", "시점"]
assert len(lines) == 3
assert lines[0] == [[35.70, 127.95], [0, 0]] # 카카오 길 선
assert lines[2] == [[35.52, 127.72], [35.4, 127.5]] # 수기 기준점 = 곧은 선 · 길찾기 안 함
assert (127.72, 127.5) not in fake.asked
assert shots["r2"][0] == [[[35.45, 127.60], [35.4, 127.5]]] # 길찾기 실패 = 곧은 선
assert (tmp_path / "B08_Quantity/milestone/auto/r1.png").read_bytes() == PNG
def test_바뀐_경로만_다시(tmp_path, monkeypatch):
fake, box = _setup(tmp_path, monkeypatch)
_save(tmp_path, DATA)
fake.shots.clear()
ms.refresh_images(tmp_path)
assert fake.shots == [] # 안 바뀜
moved = {**DATA, "bases": [BASES[0], {**BASES[1], "lat": 35.55}]}
_save(tmp_path, moved)
assert sorted(s[0] for s in fake.shots) == ["r1", "r4"] # b2 를 지나는 경로만
fake.shots.clear()
box["start"] = [127.4, 35.3] # 시점 옮김(노선 수정) = 모두
ms.refresh_images(tmp_path)
assert sorted(s[0] for s in fake.shots) == ["r1", "r2", "r4"]
fake.shots.clear()
(tmp_path / "B08_Quantity/milestone/auto/r2.png").unlink() # 그림 없음 = 다시
ms.refresh_images(tmp_path)
assert [s[0] for s in fake.shots] == ["r2"]
def test_길찾기_그림_뒤엔_다음_저장에_전체로(tmp_path, monkeypatch):
fake, _ = _setup(tmp_path, monkeypatch)
async def root(project_id):
return tmp_path
monkeypatch.setattr(ms, "_project_root", root)
monkeypatch.delenv("PYTEST_CURRENT_TEST") # [저장] 뒤 캡처 켬(시험 중엔 꺼 둠)
app = FastAPI()
app.include_router(ms.router)
client = TestClient(app)
base = f"/api/projects/{uuid4()}/quantity/milestone"
assert client.put(base, json=DATA).status_code == 200 # 답 뒤 캡처
assert sorted(s[0] for s in fake.shots) == ["r1", "r2", "r4"]
fake.shots.clear()
part = {"lines": [[[35.70, 127.95], [35.68, 127.91]]], "marks": []}
assert client.post(base + "/image/auto", params={"route": "r1"}, json=part).status_code == 200
assert [s[0] for s in fake.shots] == ["r1"] # 화면 길찾기 그림(거래처 구간만)
fake.shots.clear()
ms.refresh_images(tmp_path)
assert [(s[0], len(s[2])) for s in fake.shots] == [("r1", 4)] # 전체 경로로 다시