From 3307d7ba7234ef1aad05a2aca4fc051cb4327b36 Mon Sep 17 00:00:00 2001 From: lhl Date: Sun, 9 Aug 2026 03:18:12 +0800 Subject: [PATCH] =?UTF-8?q?test:=20=E7=9C=9F=E5=AE=9E=E6=A0=B7=E6=9C=AC?= =?UTF-8?q?=E9=9B=86=E6=88=90=E6=B5=8B=E8=AF=95=EF=BC=883=20=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=20xlsx=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _AI_USAGE_LOG.md | 3 ++- tests/test_real_samples.py | 39 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/test_real_samples.py diff --git a/_AI_USAGE_LOG.md b/_AI_USAGE_LOG.md index 8a70829..816f6f5 100644 --- a/_AI_USAGE_LOG.md +++ b/_AI_USAGE_LOG.md @@ -28,5 +28,6 @@ | 2026-08-08 23:04 | Agent 实现 | 里程碑2 Task4 实现:MergeHandler 与 TableExtractor。新建 src/genesis/parsers/merge_fill.py(forward_fill 合并单元格展开,(min_row,min_col,max_row,max_col) 1-based 范围用左上主格值填充,边界保护)与 src/genesis/parsers/table_extractor.py(column_letter 1→A/27→AA;extract_table 首行表头→其后为数据行,构建 CellValue+Provenance(row=r-header_row 从 1 起、column 字母、column_header),无矩阵时返回空表)及 tests/test_table_extractor.py(4 用例:纵向/横向合并、列字母、基本提取);TDD 验证 RED(ImportError: No module named 'genesis.parsers.merge_fill')→ GREEN(4 passed);pytest 全量 28 passed;data_models.py 未改动;提交 63d0c90 | src/genesis/parsers/merge_fill.py, src/genesis/parsers/table_extractor.py, tests/test_table_extractor.py | deepseek-v4-flash-free | | 2026-08-09 02:59 | Agent 实现 | 里程碑2 Task5 实现:FormattingDetector(取消线/背景色/批注)。新建 src/genesis/parsers/formatting_detector.py(cell_formatting 检测 strike/字体色/背景色,纯默认单元格返回 None;cell_comment 返回 CellComment;collect_comments 遍历 ws.iter_rows 收集批注)与 tests/test_formatting_detector.py(4 用例);TDD 验证 RED(ImportError)→ GREEN(4 passed);修正 brief 两处 openpyxl 3.1.5 兼容问题(① 字体 Style 对象不可变,测试用 setter 设 strike;② 默认 theme 色 .rgb 取值异常,新增 _to_rgb_hex 严格校验仅接受 6/8 位十六进制并排除纯黑);pytest 全量 32 passed;data_models.py 未改动 | src/genesis/parsers/formatting_detector.py, tests/test_formatting_detector.py | deepseek-v4-flash-free | | 2026-08-09 03:15 | Agent 实现 | 里程碑2 Task6 实现:FreeTextExtractor(自由记述型 Sheet 内容提取)。新建 src/genesis/parsers/free_text_extractor.py(extract_text_blocks 按全空行分段、行内非空单元格以「 」连接;build_free_text_table 构建占位结构化表,extraction_method="llm_from_free_text"、headers=["text"]、行内 CellValue+Provenance(row 从 1 起、column="A"、column_header="text")),后续 LLM 结构化入口;tests/test_free_text_extractor.py(2 用例:全空行分段、占位表构建);TDD 验证 RED(ImportError: No module named 'genesis.parsers.free_text_extractor')→ GREEN(2 passed);pytest 全量 34 passed;待接入 SheetNature.FREE_TEXT 分支;data_models.py 未改动;提交 a9cc3c9 | src/genesis/parsers/free_text_extractor.py, tests/test_free_text_extractor.py | deepseek-v4-flash-free | -| 2026-08-09 03:13 | Agent 实现 | 里程碑2 Task7 实现:ExcelParser 编排器(集成全部解析模块)。新建 src/genesis/parsers/excel_parser.py(ExcelParseResult dataclass:file_name/tables/comments/skipped;ExcelParser.parse 编排:open_workbook→逐 sheet sheet_matrix→空跳过→detect_sheet_type→classify_sheet→FREE_TEXT 走 extract_text_blocks+build_free_text_table(带 detected_type)→否则 merged ranges 转 tuple 后 forward_fill+extract_table→collect_comments 汇总)与 tests/test_excel_parser.py(2 用例:表型 sheet 两份(機能一覧 FUNCTION / バッチ一覧 BATCH 类型+行数断言)、自由记述 sheet extraction_method="llm_from_free_text");TDD 验证 RED(ImportError: No module named 'genesis.parsers.excel_parser')→ GREEN(2 passed);pytest 全量 36 passed;data_models.py 未改动;对照 dispatch 上下文说明:data_models 无 ParsedWorkbook 命名,按 brief 定义 ExcelParseResult | src/genesis/parsers/excel_parser.py, tests/test_excel_parser.py | deepseek-v4-flash-free | +| 2026-08-09 03:13 | Agent 实现 | 里程碑2 Task7 实现:ExcelParser 编排器(集成全部解析模块)。创建 src/genesis/parsers/excel_parser.py(ExcelParseResult dataclass:file_name/tables/comments/skipped;ExcelParser.parse 编排:open_workbook→逐 sheet sheet_matrix→空则跳过→detect_sheet_type→classify_sheet→FREE_TEXT 走 extract_text_blocks+build_free_text_table(带 detected_type)→否则 merged ranges 转 tuple 后 forward_fill+extract_table→collect_comments 汇总)与 tests/test_excel_parser.py(2 个用例:表型 sheet 两个(機能一覧 FUNCTION / バッチ一覧 BATCH 类型+行数断言)、自由记述 sheet extraction_method="llm_from_free_text");TDD 验证 RED(ImportError: No module named 'genesis.parsers.excel_parser')→ GREEN(2 passed);pytest 全量 36 passed;data_models.py 未改动;对照 dispatch 上下文说明:data_models 无 ParsedWorkbook 命名,按 brief 定义 ExcelParseResult | src/genesis/parsers/excel_parser.py, tests/test_excel_parser.py | deepseek-v4-flash-free | +| 2026-08-09 03:20 | 测试验证 | 里程碑2 Task8 实现:真实样本集成测试。创建 tests/test_real_samples.py(3 个端到端用例,各样本缺失时 pytest.skip:新規開発→機能一覧 存在且 int rows+DB定義;追加改修→tables 非空且至少一表有数据行;自由記述→存在 extraction_method="llm_from_free_text" 的表);全量验证 39 passed(含 3 个样本用例);真实样本产物: 新規開発 6 表全 openpyxl(機能一覧9/画面一覧7/帳票一覧5/DB定義20/IF定義3/バッチ一覧3); 追加改修 2 表 openpyxl(機能10/画面7)+ 改修ポイント 以 FREE_TEXT 分类改 1 行(MIXED 折叠落观察已确认); 自由記述 3 表全 llm_from_free_text 各 1 行; 3 样本均 0 批注、无空 sheet。调研结论:MIXED 已知缺口#1 在真实样本未触发断言失败(无断言触发),按 brief 保持弱断言 | tests/test_real_samples.py | deepseek-v4-flash-free | diff --git a/tests/test_real_samples.py b/tests/test_real_samples.py new file mode 100644 index 0000000..ad0d305 --- /dev/null +++ b/tests/test_real_samples.py @@ -0,0 +1,39 @@ +from pathlib import Path + +import pytest + +from genesis.parsers.excel_parser import ExcelParser + +SAMPLES = Path(__file__).resolve().parents[1] / "samples" + + +def _x(name: str) -> Path: + return SAMPLES / name + + +def test_new_dev_sample_has_tables(): + p = _x("要件定義_新規開発.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("要件定義_追加改修.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("要件定義_自由記述.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) \ No newline at end of file