| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- from app.evaluation_report_parser import EvaluationReportParser
- def test_multipath_report_becomes_structured_business_data():
- report = """## 评估报告 script_build_id=436
- ### 分支评估 branch_id=3
- **该支结论**:通过
- **目标推进**:完成核心教学段落。
- ### 分支评估 branch_id=4
- **该支结论**:部分通过
- **未通过项**:工具属性说明还需补充。
- ### 对比与建议
- **采纳建议**:组合方案 3 与方案 4。
- """
- parsed = EvaluationReportParser().parse(report, kind="multipath")
- assert parsed["subjects"] == ["方案 3", "方案 4"]
- assert [item["conclusion"] for item in parsed["itemConclusions"]] == ["通过", "部分通过"]
- assert parsed["itemConclusions"][0]["achievements"] == ["完成核心教学段落。"]
- assert parsed["recommendation"] == "采纳建议:组合方案 3 与方案 4。"
- assert "script_build_id" not in str(parsed)
- assert "branch_id" not in str(parsed)
- def test_overall_report_extracts_criteria_achievements_problems_and_next_goal():
- report = """### 评审标准
- - 内容完整性
- - 证据可靠性
- ### 已达成
- - 三个核心段落已完成。
- ### 问题详情
- - **paragraph_id=9**:收尾段落缺失。
- - 【中】数据说明仍需补充。
- ### 整体结论:部分通过
- ### 下一步引领目标
- 补齐收尾并形成闭环。
- """
- parsed = EvaluationReportParser().parse(report, kind="overall")
- assert parsed["criteria"] == ["内容完整性", "证据可靠性"]
- assert parsed["achievements"] == ["三个核心段落已完成。"]
- assert [item["summary"] for item in parsed["problems"]] == ["收尾段落缺失。", "【中】数据说明仍需补充。"]
- assert parsed["problems"][1]["severity"] == "中"
- assert parsed["conclusion"] == "部分通过"
- assert parsed["nextGoal"] == "补齐收尾并形成闭环。"
- def test_markdown_table_is_parsed_without_exposing_internal_dimension_codes():
- report = """### 维度评估
- | 维度 | 结论 | 已达成 | 问题 |
- | --- | --- | --- | --- |
- | D1 维度体系一致性 | 部分通过 | 主线统一 | 段 3 命名重复 |
- | P1 元素完整性 | 通过 | 元素齐全 | |
- """
- parsed = EvaluationReportParser().parse(report, kind="overall")
- assert parsed["criteria"] == ["维度体系一致性", "元素完整性"]
- assert [item["subject"] for item in parsed["itemConclusions"]] == [
- "维度体系一致性",
- "元素完整性",
- ]
- assert parsed["problems"][0]["summary"] == "段 3 命名重复"
- assert "D1" not in str(parsed)
- assert "P1" not in str(parsed)
- def test_json_fence_and_wrong_build_id_never_become_business_content_or_association():
- report = """## 评估报告 script_build_id=1393
- ```json
- {"script_build_id": 434, "branch_id": 99, "dimension_pass": false}
- ```
- ### 整体结论:通过
- ### 评审建议
- 保留当前主线。
- """
- parsed = EvaluationReportParser().parse(report, kind="overall")
- assert parsed["conclusion"] == "通过"
- assert parsed["recommendation"] == "保留当前主线。"
- serialized = str(parsed)
- assert "1393" not in serialized
- assert "434" not in serialized
- assert "99" not in serialized
- assert "dimension_pass" not in serialized
- def test_missing_headings_and_broken_markdown_still_extract_explicit_labels():
- report = """**整体结论**:需要重试
- 遗留问题:开头和结尾未呼应
- **下一轮目标**:重写收尾
- *** 未闭合的 Markdown
- """
- parsed = EvaluationReportParser().parse(report, kind="overall")
- assert parsed["conclusion"] == "需要重试"
- assert parsed["problems"] == [{"summary": "开头和结尾未呼应"}]
- assert parsed["nextGoal"] == "重写收尾"
- assert parsed["notices"] == []
- def test_business_numbers_are_not_removed_by_identifier_sanitizing():
- report = """### 已达成
- - 领域信息 31/32 已确认。
- - 完成 5 个段落、12 个元素和 4:3 画面说明。
- ### 整体结论:通过
- """
- parsed = EvaluationReportParser().parse(report)
- assert parsed["achievements"] == [
- "领域信息 31/32 已确认。",
- "完成 5 个段落、12 个元素和 4:3 画面说明。",
- ]
- def test_empty_or_unparseable_report_returns_stable_empty_shape():
- parsed = EvaluationReportParser().parse("```json\n{broken}\n```", kind="overall")
- assert parsed == {
- "parserVersion": 1,
- "kind": "overall",
- "subjects": [],
- "criteria": [],
- "itemConclusions": [],
- "achievements": [],
- "problems": [],
- "conclusion": None,
- "recommendation": None,
- "nextGoal": None,
- "notices": ["unparsed-report"],
- }
- def test_no_problem_markers_are_not_presented_as_warnings_and_suffix_heading_splits():
- parsed = EvaluationReportParser().parse(
- """
- ### 分支评估 branch_id=5
- **该支结论**:通过
- **目标推进**:已完成收尾。
- **未通过项**:无显著质量问题。
- **领域评估维度**(已激活并判定):
- - 烹饪常识:通过
- """,
- kind="multipath",
- )
- assert parsed["problems"] == []
- assert parsed["itemConclusions"][0]["problems"] == []
- assert "烹饪常识:通过" in parsed["criteria"]
- def test_positive_sentence_after_no_problem_marker_is_not_a_problem():
- parsed = EvaluationReportParser().parse(
- "## 问题\n无显著质量问题。脚本已达到发布标准。\n\n## 整体结论\n通过",
- kind="overall",
- )
- assert parsed["problems"] == []
- def test_multipath_report_keeps_branch_groups_and_does_not_treat_not_passed_as_achievement():
- report = """### 分支评估 branch_id=1
- **该支结论**:部分通过
- **目标推进**:
- - 领域信息库新增 5 条事实(id 54-58)。
- **未通过/存疑项**:
- - 元素创建尚未完整落地。
- **有据扎实度**:来源可指位。
- ### 分支评估 branch_id=2
- **该支结论**:部分通过
- **目标推进**:
- - 已搭建五段骨架。
- **未通过/部分通过项**:
- - 数量红线违规。
- - function_elements 全部为空。
- ### 对比与建议
- | 维度 | branch1 | branch2 | 差异依据 |
- | --- | --- | --- | --- |
- | 与本轮目标的契合度 | 高 | 高 | 各自完成主任务 |
- | 结构完备性 | 不适用 | 部分通过 | 仅方案二涉及 |
- """
- parsed = EvaluationReportParser().parse(report, kind="multipath")
- assert parsed["branchEvaluations"][0] == {
- "subject": "方案 1",
- "conclusion": "部分通过",
- "achievements": ["领域信息库新增 5 条事实(id 54-58)。"],
- "problems": ["元素创建尚未完整落地。"],
- "evidence": "来源可指位。",
- }
- assert parsed["branchEvaluations"][1]["achievements"] == ["已搭建五段骨架。"]
- assert parsed["branchEvaluations"][1]["problems"] == ["数量红线违规。", "function_elements 全部为空。"]
- assert "数量红线违规。" not in parsed["achievements"]
- assert parsed["comparisonRows"][0] == {
- "criterion": "与本轮目标的契合度",
- "candidates": [
- {"subject": "方案 1", "value": "高"},
- {"subject": "方案 2", "value": "高"},
- ],
- "basis": "各自完成主任务",
- }
|