"""품셈 PDF → 절별 md 도구(`_pipeline/pum_md_tool.py`) — 순수 함수 · 산림 차례 개수. 규칙: `resources/knowledge/original/원가계산/_품셈md_작성규칙.md`. """ import sys from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] sys.path.insert(0, str(ROOT / "resources/knowledge/original/_pipeline")) import pum_md_tool as tool # noqa: E402 def test_parse_toc_strips_leaders_and_reads_appendix(): lines = ["제1장", "적용기준 ·········", "1", "1-1", "일반사항 ·····", "1", "부록 ······", "204"] got = tool.parse_toc(lines) assert [(e.ident, e.name, e.page) for e in got] == [ ("제1장", "적용기준", 1), ("1-1", "일반사항", 1), ("부록", "", 204), ] with pytest.raises(ValueError): tool.parse_toc(["엉뚱한 줄", "1"]) def test_key_ignores_spaces_dot_after_number_and_middle_dots(): assert tool.key("9-5. 발파암") == tool.key("9-5 발파암") assert tool.key("[부록1]할인") == tool.key("부록1 할인") assert tool.key("보수·복구") == tool.key("보수․복구") def test_heading_pattern_by_number_only(): sec = tool.heading_pattern("7-1") assert sec.match("7-1. 벌도") assert not sec.match("7-11. 동력상하차기") # 번호가 앞머리만 같음 assert not sec.match("7-1-1. 항") assert tool.heading_pattern("제1장").match("제1장적용기준") assert not tool.heading_pattern("제1장").match("제10장자재") assert tool.heading_pattern("부록1").match("[부록1]할인") assert not tool.heading_pattern("부록1").match("[부록10]x") def test_respace_takes_toc_spacing_but_body_glyphs(): toc = "임산물 운반로 신설 및 보수․복구" assert tool.respace("임산물운반로신설및보수·복구", toc) == "임산물 운반로 신설 및 보수·복구" # 차례 오타(조림 ≠ 조립) — 본문 그대로 assert tool.respace("철근현장가공및조립", "철근 현장가공 및 조림") == "철근현장가공및조립" def test_heading_text_keeps_number_dot(): entry = tool.Entry("4-5", "벌도 위험목 점검", 51) assert tool.heading_text(entry, "4-5. 벌도위험목점검") == "4-5. 벌도 위험목 점검" assert tool.section_name(entry, "4-5. 벌도위험목점검") == "벌도 위험목 점검" chapter = tool.Entry("제2장", "소요재료 및 기계손료", 28) assert tool.heading_text(chapter, "제2장소요재료및기계손료") == "제2장 소요재료 및 기계손료" def test_section_file_name(): chapter = tool.Entry("제10장", "자재․장비 운반", 143) section = tool.Entry("10-5", "목재 운반/적재", 150) got = tool.section_file(Path("본문"), chapter, section) assert got.as_posix() == "본문/제10장_자재․장비_운반/10-05_목재_운반적재.md" def test_head_round_trip(tmp_path): path = tmp_path / "a.md" path.write_text( tool.head_text({"절": "9-5. 발파암", "상태": "대기"}) + "\n본문\n", encoding="utf-8" ) head = tool.read_head(path) assert list(head) == list(tool.HEAD_KEYS) assert head["절"] == "9-5. 발파암" and head["상태"] == "대기" and head["작성"] == "" def test_forest_toc_counts(): """산림 차례 — 14장 · 189절(PDF 3~12쪽).""" pymupdf = pytest.importorskip("pymupdf") book = tool.BOOKS["산림"] with pymupdf.open(book["pdf"]) as doc: entries = tool.toc_entries(doc, *book["toc"]) assert sum(e.ident.startswith("제") for e in entries) == 14 assert sum(e.ident.count("-") == 1 for e in entries) == 189