test: 真实样本 Word 解析集成测试(模板/规则/说明书画属write)
This commit is contained in:
@@ -66,3 +66,4 @@
|
||||
| 2026-08-10 | Agent 实现 | Phase3 Task2 实现:WordTemplateParser 章构成/占位符/样式名提取。新建 src/genesis/parsers/_word_common.py(heading_level 共享 helper,Task2/3 复用,从 Heading N 样式名解析大纲级别,非数字/无后缀兜底 1)与 src/genesis/parsers/word_template_parser.py(PLACEHOLDER_RE 统一占位符正则 {{键名}}/{{键名:章节名}};Heading 段落→heading 章标记、bookmarkStart→bookmark、占位符→placeholder 并写 placeholders{名:段落上下文};styles 提取 defined/used 样式名集合去重);tests/test_word_template_parser.py 按 brief 8 用例(6 解析 + 2 heading_level 兜底分支);覆盖补齐:bookmark 用例增加无 name 的 bookmarkStart 覆盖 if name 假分支(98%→100%);TDD 验证 RED(ModuleNotFoundError: No module named 'genesis.parsers._word_common')→ GREEN(聚焦 8 passed);pytest 全量 140 passed 覆盖 100.00%(841 stmts/200 br),fail_under=99 达标 | src/genesis/parsers/_word_common.py, src/genesis/parsers/word_template_parser.py, tests/test_word_template_parser.py, _AI_USAGE_LOG.md | deepseek-v4-flash-free |
|
||||
| 2026-08-10 | Agent 实现 | Phase3 Task3 实现:RuleDocParser 规则文档 Markdown 化与分类。新建 src/genesis/parsers/rule_doc_parser.py(body 级遍历保段落/表格交错顺序;Heading N→#×N;列表双通道检测 List 样式或 ・/-/• 前缀;表格→GFM;空段→空行;file_type 固定 word、hash=sha256 hex;复用 _word_common.heading_level 无本地重复)与 tests/test_rule_doc_parser.py 按 brief 6 用例;覆盖补齐:test_parse_empty_document 增加 doc.add_paragraph("") 使空段分支(原 new_document 无任何 w:p 不进分支)达 100%;TDD 验证 RED(ModuleNotFoundError: No module named 'genesis.parsers.rule_doc_parser')→ GREEN(聚焦 6 passed);pytest 全量 146 passed 覆盖 100.00%(886 stmts/218 br),fail_under=99 达标 | src/genesis/parsers/rule_doc_parser.py, tests/test_rule_doc_parser.py, _AI_USAGE_LOG.md | deepseek-v4-flash-free |
|
||||
| 2026-08-10 | Agent 实现 | Phase3 Task4 实现:SourceParser 门面全量输入聚合。新建 src/genesis/parsers/source_aggregator.py(角色显式传参无隐式猜测;requirements 校验 .xlsx/.xls 后缀聚合 tables/comments;template 校验 .docx 用 WordTemplateParser 解析;write_instruction+rule 校验 .docx 按 category='write' 归入 rule_docs;不存在抛 FileNotFoundError、未知扩展名抛 ValueError('不支持的文件类型: ...');image_analyses=[]/existing_system=None 固定)与 tests/test_source_aggregator.py 按 brief 6 用例 + 补 4 用例(模板未知扩展名、规则路径文件缺失、requirements/规则无扩展名兜底 '无扩展名' 文案,覆盖 51/62 行缺失与 or 表达式分支)达 100%;TDD 验证 RED(ModuleNotFoundError: No module named 'genesis.parsers.source_aggregator')→ GREEN(聚焦 10 passed);pytest 全量 156 passed 覆盖 100.00%(929 stmts/236 br),fail_under=99 达标 | src/genesis/parsers/source_aggregator.py, tests/test_source_aggregator.py, _AI_USAGE_LOG.md | deepseek-v4-flash-free |
|
||||
| 2026-08-10 | 测试验证 | Phase3 Task5 实现:真实样本 Word 解析集成测试。tests/test_real_samples.py 追加 4 用例(保留现有 4 个 Excel 用例与 _x 辅助):模板→7 H1(はじめに…バッチ一覧)+section:introduction/doc_title 占位符+template_start 书签;记入規則→category=write/file_type=word/# 1. 機能一覧の書き方/- 機能ID は F001 から連番で付与する。(・前缀双通道检测);做成説明書→category=write/# 2. 機能一覧;全量组装→tables 非空+template 非空+rule_docs==2 且全 write;聚焦测试 8 passed 无 skip;pytest 全量 160 passed 覆盖 100.00%(929 stmts/236 br),fail_under=99 达标 | tests/test_real_samples.py, _AI_USAGE_LOG.md | deepseek-v4-flash-free |
|
||||
|
||||
@@ -3,10 +3,17 @@ from pathlib import Path
|
||||
import pytest
|
||||
|
||||
from genesis.parsers.excel_parser import ExcelParser
|
||||
from genesis.parsers.word_template_parser import WordTemplateParser
|
||||
from genesis.parsers.rule_doc_parser import RuleDocParser
|
||||
from genesis.parsers.source_aggregator import SourceParser
|
||||
|
||||
SAMPLES = Path(__file__).resolve().parents[1] / "samples"
|
||||
|
||||
|
||||
def _d(name: str) -> Path:
|
||||
return SAMPLES / name
|
||||
|
||||
|
||||
def _x(name: str) -> Path:
|
||||
return SAMPLES / name
|
||||
|
||||
@@ -57,4 +64,60 @@ def test_mixed_sample_segments_detected():
|
||||
# 碎片段含 ・ 与 ■ 两行文本
|
||||
ft = [p for p in mixed.paragraphs if p.kind == "free_text"][0]
|
||||
assert "改修ポイント" in (ft.text or "")
|
||||
assert "対象期間" in (ft.text or "")
|
||||
assert "対象期間" in (ft.text or "")
|
||||
|
||||
|
||||
def test_word_template_sample_chapters_and_placeholders():
|
||||
p = _d("概要設計書テンプレート.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("記入規則.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("概要設計做成説明書.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("要件定義_新規開発.xlsx")
|
||||
template = _d("概要設計書テンプレート.docx")
|
||||
rule = _d("記入規則.docx")
|
||||
instr = _d("概要設計做成説明書.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)
|
||||
Reference in New Issue
Block a user