Files
cad-agent/tests/test_cad_tools.py
T
gjm 0656397a68 test(review): 新增 pytest 离线回归网,锁定 dwg_review 既有行为
在改动审查流水线(确定性检查前置 / 结论结构化 / 证据交叉校验)之前,
先立一张离线、确定性、秒级的回归网。

- tests/fakes.py:假 LLM + 假 MCP 基座 + 响应构造器(ok_text/ok_image/err)
  + make_ctx/make_evidence,绝不触网、不读密钥
- 10 个模块共 134 用例:
  mcp_client / llm_client / cad_tools / checklist / config /
  planning / evidence / review / report / annotator
- pytest.ini(testpaths=tests)+ requirements-dev.txt + 根 conftest.py
  (sys.path + RENDER_WAIT=0 / REPORT_DIR=tmp fixture)
2026-10-14 19:07:27 +08:00

103 lines
3.9 KiB
Python

"""`dwg_review.cad_tools` 单元测试。"""
from dwg_review.cad_tools import CadTools, is_write_tool
from dwg_review.mcp_client import result_json
from tests.fakes import FakeMcpClient, ok_text, tool_schema
# ---------------------------------------------------------------------------
# 写类工具判定
# ---------------------------------------------------------------------------
def test_write_prefixes_detected():
for name in ("add_leader_annotation", "delete_entities", "draw_line", "set_layer"):
assert is_write_tool(name) is True
def test_write_exact_names_detected():
assert is_write_tool("set_entity_properties") is True
assert is_write_tool("highlight_entities") is True
def test_readonly_tools_are_not_write():
for name in ("query_entities", "get_text_content", "zoom_to_window", "find_zero_length"):
assert is_write_tool(name) is False
# ---------------------------------------------------------------------------
# 注册表
# ---------------------------------------------------------------------------
def test_registry_built_from_client():
client = FakeMcpClient()
tools = CadTools(client)
assert "query_entities" in tools.names
assert tools.has("get_viewport_screenshot") is True
assert tools.has("__nope__") is False
assert tools.names == sorted(tools.names)
def test_describe_returns_tool_dict():
client = FakeMcpClient()
tools = CadTools(client)
desc = tools.describe("query_entities")
assert desc["name"] == "query_entities"
assert "inputSchema" in desc
def test_refresh_picks_up_new_tools():
client = FakeMcpClient(tools=[tool_schema("a")])
tools = CadTools(client)
assert tools.names == ["a"]
client._tools = [tool_schema("a"), tool_schema("b")]
tools.refresh()
assert tools.names == ["a", "b"]
# ---------------------------------------------------------------------------
# openai_tools
# ---------------------------------------------------------------------------
def test_openai_tools_format():
client = FakeMcpClient(tools=[tool_schema("query_entities", "查询", {"window": {"type": "object"}})])
entry = CadTools(client).openai_tools()[0]
assert entry["type"] == "function"
assert entry["function"]["name"] == "query_entities"
assert entry["function"]["description"] == "查询"
assert entry["function"]["parameters"]["properties"] == {"window": {"type": "object"}}
def test_openai_tools_defaults_schema_when_missing():
client = FakeMcpClient(tools=[{"name": "bare", "description": ""}])
entry = CadTools(client).openai_tools()[0]
assert entry["function"]["parameters"] == {"type": "object", "properties": {}}
def test_openai_tools_names_filter():
client = FakeMcpClient()
names = CadTools(client).openai_tools(names={"query_entities", "get_layers"})
assert sorted(n["function"]["name"] for n in names) == ["get_layers", "query_entities"]
# ---------------------------------------------------------------------------
# call
# ---------------------------------------------------------------------------
def test_call_returns_normalized_response():
client = FakeMcpClient(responses={"query_entities": ok_text({"total": 7})})
tools = CadTools(client)
assert result_json(tools.call("query_entities", {"window": {}})) == {"total": 7}
assert client.calls[-1]["name"] == "query_entities"
assert client.calls[-1]["arguments"] == {"window": {}}
def test_call_marks_write_tools():
client = FakeMcpClient()
tools = CadTools(client)
tools.call("add_leader_annotation", {"text": "x"})
tools.call("query_entities", {"window": {}})
assert client.calls[0]["is_write"] is True
assert client.calls[1]["is_write"] is False
def test_call_explicit_is_write_overrides_inference():
client = FakeMcpClient()
CadTools(client).call("query_entities", {}, is_write=True)
assert client.calls[-1]["is_write"] is True