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

119 lines
4.2 KiB
Python

"""[저장]이 「행은 있는데 설계가 빈 측점」을 채우는지 (2026-09-09).
재생성이 `cross_sections` 행을 지우고 다시 쓰면 `data.design` 에 면적 4키만 남는다.
`get_cross_section_designs` 는 `ground_type` 있는 줄만 담으므로 그 상태는 「설계 없음」이고,
B08 토적표가 통째로 0 이 됐다(창 셋에서 같은 증상). 예전에는 체인이 뒤이어 부르는 [확정]이
그 자리를 채워 가려져 있었다.
⚠ **값이 있는 행은 안 건드린다**가 이 시험의 핵심이다 — 사용자 조작값·이월분이 거기 있다.
"""
from __future__ import annotations
import asyncio
import sys
from pathlib import Path
from typing import Any
import pytest
PROJECT_ROOT = Path(__file__).resolve().parents[2]
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
import B06_Section.B06_Section_Router_Confirm as confirm # noqa: E402
class _Conn:
async def begin(self) -> None:
return None
async def commit(self) -> None:
return None
async def rollback(self) -> None:
return None
class _Acquire:
async def __aenter__(self) -> _Conn:
return _Conn()
async def __aexit__(self, *_: Any) -> None:
return None
class _Pool:
def acquire(self) -> _Acquire:
return _Acquire()
def _async(value: Any):
async def _inner(*_: Any, **__: Any) -> Any:
return value
return _inner
def _run_save(monkeypatch: pytest.MonkeyPatch, missing: list[float]) -> list[float]:
"""`save_sections` 를 돌리고 **기본 설계를 계산하라고 넘긴 측점 목록**을 돌려준다."""
seen: list[float] = []
monkeypatch.setattr(confirm, "get_db_pool", lambda: _Pool())
monkeypatch.setattr(
confirm, "get_longitudinal_section", _async({"longitudinal_file_path": "long.json"})
)
monkeypatch.setattr(confirm, "get_project_storage_relative_path", _async("1/3/proj"))
monkeypatch.setattr(confirm, "get_cross_section_chainages", _async([0.0, 20.0, 40.0]))
monkeypatch.setattr(confirm, "get_cross_sections_missing_design_chainages", _async(missing))
monkeypatch.setattr(confirm, "resolve_stored_project_path", lambda _p: str(PROJECT_ROOT))
# 행 자체가 없는 측점은 이 시험의 관심사가 아니다 — 빈 목록으로 고정한다.
monkeypatch.setattr(confirm, "_rowless_station_chainages", lambda *_a, **_k: [])
def _spy(_root, _path, chainages, _standard):
seen.extend(chainages)
return [(value, {"ground_type": "soil"}) for value in chainages]
monkeypatch.setattr(confirm, "_compute_default_designs", _spy)
monkeypatch.setattr(confirm, "_apply_section_edits", _async(None))
monkeypatch.setattr(confirm, "_recompute_stored_designs", _async(None))
from uuid import UUID
response = asyncio.run(
confirm.save_sections(
project_id=UUID("fa76c162-71c7-46e5-a95d-fb3930665a45"), route_id=184, request=None
)
)
assert getattr(response, "confirmed", None) is False, response
return seen
def test_설계가_빈_측점을_채운다(monkeypatch: pytest.MonkeyPatch) -> None:
seen = _run_save(monkeypatch, [20.0, 40.0])
assert sorted(seen) == [20.0, 40.0]
def test_값이_있는_행은_안_건드린다(monkeypatch: pytest.MonkeyPatch) -> None:
"""빈 측점이 없으면 기본 설계를 아예 계산하지 않는다 — 덮어쓸 일이 없다."""
seen = _run_save(monkeypatch, [])
assert seen == []
def test_빈_설계의_뜻이_ground_type_없음이다() -> None:
"""판정은 `get_cross_sections_missing_design_chainages` 한 곳에서만 한다."""
import inspect
from B06_Section.B06_Section_Repository import get_cross_sections_missing_design_chainages
source = inspect.getsource(get_cross_sections_missing_design_chainages)
assert 'design.get("ground_type")' in source
def test_저장도_확정과_같은_판정을_쓴다() -> None:
"""두 갈래가 같은 조회를 써야 「저장했는데 확정과 다르다」가 안 생긴다."""
import inspect
source = inspect.getsource(confirm.save_sections)
assert "get_cross_sections_missing_design_chainages" in source