test(m02): 구조물 정의 시험의 판 숫자 고정 제거 — 저장하면 판 + 1 · 이력 파일 생김 꼴

- 판 1 = 옛 레지스트리 검사는 이력 판_1 로 · 지금 정의는 검사 통과 · 종류·옵션 수 일치
- 쓰기 시험은 사본 정의의 지금 판 기준 · 진짜 구조물정의.json 안 씀

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NPJGtfXo6GMbcpiboQC4uK
This commit is contained in:
2026-10-06 00:05:30 +09:00
co-authored by Claude Opus 5.5
parent a894869719
commit b02cd0bb99
@@ -3,7 +3,7 @@
못박는 것 못박는 것
- 판 1 = 옛 레지스트리 그대로 옮김(37종 · 옵션 235 · 키 그대로) · 검사 통과. - 판 1 = 옛 레지스트리 그대로 옮김(37종 · 옵션 235 · 키 그대로) · 검사 통과.
- 읽기 = 로그인 누구나 · 쓰기 = 시스템 관리자만(403). - 읽기 = 로그인 누구나 · 쓰기 = 시스템 관리자만(403).
- 저장마다 판 +1 · 앞 판은 `구조물정의_이력/판_N.json` · 낡은 판 409 · 틀린 정의 422(안 씀). - 저장마다 판 +1(지금 판에서) · 앞 판은 `구조물정의_이력/판_N.json` · 낡은 판 409 · 틀린 정의 422(안 씀).
- 검사 = 키 겹침 · 꼴 · 규칙 대상 있음 · 그룹 형상. - 검사 = 키 겹침 · 꼴 · 규칙 대상 있음 · 그룹 형상.
- 저장한 정의를 `/structure-types` 가 바로 읽음 · 프로젝트 저장에 정의 판 · 없는 키 값 보존. - 저장한 정의를 `/structure-types` 가 바로 읽음 · 프로젝트 저장에 정의 판 · 없는 키 값 보존.
""" """
@@ -49,12 +49,16 @@ def _client(session: dict) -> TestClient:
def test_판1_은_옛_레지스트리_그대로_검사_통과() -> None: def test_판1_은_옛_레지스트리_그대로_검사_통과() -> None:
doc = definition.read() doc = definition.read_version(1)
assert doc["판"] == 1 and len(doc["types"]) == 37 assert doc["판"] == 1 and len(doc["types"]) == 37
assert sum(len(t["options"]) for t in doc["types"]) == 235 assert sum(len(t["options"]) for t in doc["types"]) == 235
assert len(load_structure_types()) == 37
assert sum(len(t.options) for t in load_structure_types()) == 235
assert definition.check(doc) == [] assert definition.check(doc) == []
now = definition.read()
assert now["판"] >= 1 and definition.check(now) == []
assert len(load_structure_types()) == len(now["types"])
assert sum(len(t.options) for t in load_structure_types()) == sum(
len(t["options"]) for t in now["types"]
)
assert [g["이름"] for g in doc["그룹"]["pipe"]] == ["관", "관 보호공(유입)", "관 보호공(유출)"] assert [g["이름"] for g in doc["그룹"]["pipe"]] == ["관", "관 보호공(유입)", "관 보호공(유출)"]
assert {t["group"] for t in doc["types"]} <= set(doc["구조물군"]) assert {t["group"] for t in doc["types"]} <= set(doc["구조물군"])
@@ -62,26 +66,28 @@ def test_판1_은_옛_레지스트리_그대로_검사_통과() -> None:
def test_읽기는_누구나_쓰기는_시스템_관리자만(copy) -> None: def test_읽기는_누구나_쓰기는_시스템_관리자만(copy) -> None:
user = _client(USER) user = _client(USER)
got = user.get(URL) got = user.get(URL)
assert got.status_code == 200 and got.json()["판"] == 1 v = json.loads(copy.read_text("utf-8"))["판"]
assert user.put(URL, json={"판": 1, "정의": got.json()}).status_code == 403 assert got.status_code == 200 and got.json()["판"] == v
assert json.loads(copy.read_text("utf-8"))["판"] == 1 # 안 씀 assert user.put(URL, json={"판": v, "정의": got.json()}).status_code == 403
assert json.loads(copy.read_text("utf-8"))["판"] == v # 안 씀
def test_저장마다_판_더하기_1_앞_판은_이력_structure_types_가_바로_읽음(copy) -> None: def test_저장마다_판_더하기_1_앞_판은_이력_structure_types_가_바로_읽음(copy) -> None:
admin = _client(ADMIN) admin = _client(ADMIN)
doc = admin.get(URL).json() doc = admin.get(URL).json()
v = doc["판"]
tid = doc["types"][0]["type_id"] tid = doc["types"][0]["type_id"]
doc["types"][0]["name"] = "이름 바꿈" doc["types"][0]["name"] = "이름 바꿈"
res = admin.put(URL, json={"판": 1, "정의": doc}) res = admin.put(URL, json={"판": v, "정의": doc})
assert res.status_code == 200, res.text assert res.status_code == 200, res.text
assert res.json()["판"] == 2 assert res.json()["판"] == v + 1
old = json.loads((copy.parent / "구조물정의_이력" / "판_1.json").read_text("utf-8")) old = json.loads((copy.parent / "구조물정의_이력" / f"판_{v}.json").read_text("utf-8"))
assert old["판"] == 1 and old["types"][0]["name"] != "이름 바꿈" assert old["판"] == v and old["types"][0]["name"] != "이름 바꿈"
seen = {t["type_id"]: t for t in admin.get(TYPES).json()["types"]} seen = {t["type_id"]: t for t in admin.get(TYPES).json()["types"]}
assert seen[tid]["name"] == "이름 바꿈" and len(seen) == 37 assert seen[tid]["name"] == "이름 바꿈" and len(seen) == len(doc["types"])
assert admin.put(URL, json={"판": 1, "정의": doc}).status_code == 409 # 낡은 판 assert admin.put(URL, json={"판": v, "정의": doc}).status_code == 409 # 낡은 판
assert admin.put(URL, json={"판": 2, "정의": res.json()}).json()["판"] == 3 assert admin.put(URL, json={"판": v + 1, "정의": res.json()}).json()["판"] == v + 2
assert (copy.parent / "구조물정의_이력" / "판_2.json").is_file() assert (copy.parent / "구조물정의_이력" / f"판_{v + 1}.json").is_file()
def _rule(doc: dict) -> tuple[str, dict, dict]: def _rule(doc: dict) -> tuple[str, dict, dict]:
@@ -96,6 +102,7 @@ def _rule(doc: dict) -> tuple[str, dict, dict]:
def test_검사_키_겹침_꼴_규칙_대상_형상(copy) -> None: def test_검사_키_겹침_꼴_규칙_대상_형상(copy) -> None:
admin = _client(ADMIN) admin = _client(ADMIN)
base = admin.get(URL).json() base = admin.get(URL).json()
v = base["판"]
tid, up, down = _rule(base) tid, up, down = _rule(base)
good = { good = {
"종류": tid, "종류": tid,
@@ -133,13 +140,13 @@ def test_검사_키_겹침_꼴_규칙_대상_형상(copy) -> None:
bad(모르는칸=1), bad(모르는칸=1),
] ]
for i, doc in enumerate(cases): for i, doc in enumerate(cases):
res = admin.put(URL, json={"판": 1, "정의": doc}) res = admin.put(URL, json={"판": v, "정의": doc})
assert res.status_code == 422, (i, res.text) assert res.status_code == 422, (i, res.text)
assert json.loads(copy.read_text("utf-8"))["판"] == 1 # 거절되면 안 씀 assert json.loads(copy.read_text("utf-8"))["판"] == v # 거절되면 안 씀
assert not (copy.parent / "구조물정의_이력").exists() assert not (copy.parent / "구조물정의_이력").exists()
shaped = bad(종류={tid: {"기준측점": False}}) shaped = bad(종류={tid: {"기준측점": False}})
shaped["그룹"]["pipe"][0]["형상"] = {"길이": {"받기": True, "뜻": "관 길이"}} shaped["그룹"]["pipe"][0]["형상"] = {"길이": {"받기": True, "뜻": "관 길이"}}
assert admin.put(URL, json={"판": 1, "정의": shaped}).status_code == 200 assert admin.put(URL, json={"판": v, "정의": shaped}).status_code == 200
def test_프로젝트_저장에_정의_판_없는_키_값은_남김(copy, tmp_path) -> None: def test_프로젝트_저장에_정의_판_없는_키_값은_남김(copy, tmp_path) -> None:
@@ -154,5 +161,5 @@ def test_프로젝트_저장에_정의_판_없는_키_값은_남김(copy, tmp_pa
) )
assert save_structures(root, [item], base_revision=0) == 1 assert save_structures(root, [item], base_revision=0) == 1
raw = json.loads(Path(root, "B05_Profile", "route", "structures.json").read_text("utf-8")) raw = json.loads(Path(root, "B05_Profile", "route", "structures.json").read_text("utf-8"))
assert raw["definition_version"] == 1 assert raw["definition_version"] == definition.read()["판"]
assert load_structures(root)[1][0].options["지난정의키"] == "옛값" assert load_structures(root)[1][0].options["지난정의키"] == "옛값"