from pathlib import Path import pytest from genesis.parsers.excel_parser import ExcelParser from genesis.parsers.rule_doc_parser import RuleDocParser from genesis.parsers.source_aggregator import SourceParser from genesis.parsers.word_template_parser import WordTemplateParser SAMPLES = Path(__file__).resolve().parents[1] / "sample" def _d(name: str) -> Path: return SAMPLES / name def _x(name: str) -> Path: return SAMPLES / name def test_new_dev_sample_has_tables(): p = _x("requirements_newdev.xlsx") if not p.exists(): pytest.skip("样本缺失") result = ExcelParser().parse(p) by_name = {t.name: t for t in result.tables} assert "機能一覧" in by_name assert by_name["機能一覧"].rows assert any(t.name == "DB定義" for t in result.tables) def test_additional_modification_has_tables(): p = _x("requirements_enhancement.xlsx") if not p.exists(): pytest.skip("样本缺失") result = ExcelParser().parse(p) assert result.tables assert any(t.rows for t in result.tables) def test_free_text_sample_detected(): p = _x("requirements_freetext.xlsx") if not p.exists(): pytest.skip("样本缺失") result = ExcelParser().parse(p) assert any(t.extraction_method == "llm_from_free_text" for t in result.tables) def test_mixed_sample_segments_detected(): p = _x("requirements_mixed.xlsx") if not p.exists(): pytest.skip("样本缺失") result = ExcelParser().parse(p) by_name = {t.name: t for t in result.tables} assert "機能一覧" in by_name assert result.mixed, "混合样本应产出段落" mixed = result.mixed[0] assert len(mixed.paragraphs) == 2 # 表格段 + 碎片段(・/■ 连续) assert [p.kind for p in mixed.paragraphs] == ["table", "free_text"] # 表格段无碎片污染 table = [p.table for p in mixed.paragraphs if p.kind == "table"][0] assert table.rows[0]["機能ID"].value == "F101" assert len(table.rows) == 3 # 碎片段含 ・ 与 ■ 两行文本 ft = [p for p in mixed.paragraphs if p.kind == "free_text"][0] assert "改修ポイント" in (ft.text or "") assert "対象期間" in (ft.text or "") def test_word_template_sample_chapters_and_placeholders(): p = _d("template_design_ja.docx") if not p.exists(): pytest.skip("样本缺失") result = WordTemplateParser().parse(p) headings = [s for s in result.sections if s.type == "heading"] h1 = [h for h in headings if h.level == 1] assert len(h1) == 7 assert h1[0].name == "1. はじめに" assert h1[-1].name == "7. バッチ一覧" assert "section:introduction" in result.placeholders assert "doc_title" in result.placeholders bookmarks = [s for s in result.sections if s.type == "bookmark"] assert len(bookmarks) == 1 assert bookmarks[0].name == "template_start" def test_rule_doc_sample_markdown_and_category(): p = _d("rules_entry_ja.docx") if not p.exists(): pytest.skip("样本缺失") result = RuleDocParser().parse(p, category="write") assert result.category == "write" assert result.file_type == "word" assert "# 1. 機能一覧の書き方" in result.markdown_content assert "- 機能ID は F001 から連番で付与する。" in result.markdown_content def test_write_instruction_sample_category_write(): p = _d("rules_design_ja.docx") if not p.exists(): pytest.skip("样本缺失") result = RuleDocParser().parse(p, category="write") assert result.category == "write" assert "# 2. 機能一覧" in result.markdown_content def test_source_parser_full_sample_assembly(): xlsx = _x("requirements_newdev.xlsx") template = _d("template_design_ja.docx") rule = _d("rules_entry_ja.docx") instr = _d("rules_design_ja.docx") if not all(p.exists() for p in [xlsx, template, rule, instr]): pytest.skip("样本缺失") result = SourceParser().parse( requirement_paths=[xlsx], template_path=template, write_instruction_paths=[instr], rule_paths=[rule], ) assert result.tables assert result.template is not None assert len(result.rule_docs) == 2 assert all(r.category == "write" for r in result.rule_docs)