From daccc734bfc17e939aaf176f2369f2ce1fd749d6 Mon Sep 17 00:00:00 2001 From: LittleGuo Date: Wed, 14 Oct 2026 19:09:56 +0800 Subject: [PATCH] =?UTF-8?q?test(review):=20=E6=8A=8A=205=20=E5=A4=84?= =?UTF-8?q?=E6=97=A2=E6=9C=89=E7=91=95=E7=96=B5=E9=94=81=E6=88=90=20*=5Fkn?= =?UTF-8?q?own=5Fgap=20=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 让既有瑕疵可见,而不是被当成正确行为;改 1~3(确定性检查前置/结论结构化/ 证据交叉校验)时可据此判断行为是否被改变。 - bbox_to_window 含非数值 → ValueError(上游只判长度) - summarize / extract_issues 硬下标 f['frame'] → KeyError - annotate 的 created 无去重(同 handle 产生重复批注) - extract_issues 单行 ```json[...]``` 围栏剥离失败 → [] - result_json 文本 'null' → None(与「无 text 返回 default」语义易混) --- tests/test_annotator.py | 15 +++++++++++++++ tests/test_evidence.py | 8 ++++++++ tests/test_mcp_client.py | 5 +++++ tests/test_report.py | 23 +++++++++++++++++++++++ 4 files changed, 51 insertions(+) diff --git a/tests/test_annotator.py b/tests/test_annotator.py index 1240316..46dbe3a 100644 --- a/tests/test_annotator.py +++ b/tests/test_annotator.py @@ -120,6 +120,21 @@ def test_annotate_handles_multiple_created_entities(): assert created == ["N1", "N2"] +def test_annotate_created_not_deduped_known_gap(): + """已知瑕疵:同一 handle 出现两次会创建两条批注(created 无去重,仅 highlighted 去重)。""" + ctx = make_ctx(client=build_client()) + created, highlighted = annotate( + ctx, + [ + {"handle": "A", "severity": "high", "message": "第一次"}, + {"handle": "A", "severity": "high", "message": "第二次"}, + ], + log=lambda *a: None, + ) + assert created == ["NEW1", "NEW1"] # 重复批注(期望去重) + assert highlighted == ["A"] # 高亮已去重 + + def test_annotate_propagates_protocol_error_on_detail(): ctx = make_ctx(client=FakeMcpClient(responses={"get_entity_detail": McpError(-32602, "bad")})) # annotate 只兜 add_leader/highlight 的错;detail 的协议错误会向上冒泡(现状行为) diff --git a/tests/test_evidence.py b/tests/test_evidence.py index fe498cf..1964a3d 100644 --- a/tests/test_evidence.py +++ b/tests/test_evidence.py @@ -1,5 +1,7 @@ """`dwg_review.phases.evidence` 单元测试。""" +import pytest + from dwg_review.phases.evidence import bbox_to_window, collect_frame from tests.fakes import FakeMcpClient, frame, make_ctx, ok_image, ok_text @@ -13,6 +15,12 @@ def test_bbox_to_window_mapping(): } +def test_bbox_to_window_non_numeric_known_gap(): + """已知瑕疵:4 元素但含非数值的 bbox 会抛 ValueError,上游 collect_frame 只判长度。""" + with pytest.raises(ValueError): + bbox_to_window([0, "a", 10, 10]) + + def test_collect_frame_returns_none_for_missing_bbox(): ctx = make_ctx(client=FakeMcpClient()) assert collect_frame(ctx, 1, {}) is None diff --git a/tests/test_mcp_client.py b/tests/test_mcp_client.py index feefb82..1287d60 100644 --- a/tests/test_mcp_client.py +++ b/tests/test_mcp_client.py @@ -63,6 +63,11 @@ def test_result_json_returns_default_when_no_text(): assert result_json(None, "D") == "D" +def test_result_json_null_text_known_gap(): + """已知瑕疵:文本 'null' 是合法 JSON,解析为 None,与「无 text 返回 default」语义易混。""" + assert result_json(ok_text("null"), "D") is None + + def test_result_texts_tolerates_malformed_response(): assert result_texts(None) == [] assert result_texts({}) == [] diff --git a/tests/test_report.py b/tests/test_report.py index 7111071..aaa17c1 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -2,6 +2,8 @@ import json +import pytest + from dwg_review.phases.report import extract_issues, save_report, summarize from tests.fakes import FakeLlmClient, make_ctx @@ -44,6 +46,13 @@ def test_summarize_falls_back_to_raw_input_on_error(): assert any("汇总失败" in line for line in logs) +def test_summarize_missing_frame_key_known_gap(): + """已知瑕疵:summarize 用硬下标 f['frame'],findings 缺该键直接 KeyError。""" + ctx = make_ctx(llm=FakeLlmClient(text="x")) + with pytest.raises(KeyError): + summarize(ctx, [{"finding": "缺 frame 键"}], log=lambda *a: None) + + # --------------------------------------------------------------------------- # extract_issues # --------------------------------------------------------------------------- @@ -85,6 +94,20 @@ def test_extract_issues_returns_empty_when_not_a_list(): assert extract_issues(ctx, findings_fixture(), log=lambda *a: None) == [] +def test_extract_issues_single_line_fence_known_gap(): + """已知瑕疵:围栏剥离依赖换行,单行 ```json[...]``` 会残留 json 前缀 → 解析失败。""" + llm = FakeLlmClient(text_script=['```json[{"frame": 1, "message": "z"}]```']) + ctx = make_ctx(llm=llm) + assert extract_issues(ctx, findings_fixture(), log=lambda *a: None) == [] + + +def test_extract_issues_missing_frame_key_known_gap(): + """已知瑕疵:extract_issues 同样用硬下标 f['frame'],findings 缺该键直接 KeyError。""" + ctx = make_ctx(llm=FakeLlmClient(text="[]")) + with pytest.raises(KeyError): + extract_issues(ctx, [{"finding": "缺 frame 键"}], log=lambda *a: None) + + # --------------------------------------------------------------------------- # save_report # ---------------------------------------------------------------------------