"世界上有两种Agent开发者:一种在凌晨3点被叫起来修bug,另一种在写测试。前者很忙,后者睡得很香。选择权在你。"
为什么Agent需要测试?
传统软件测试是确定性的——输入A一定得到B。但Agent测试面临独特挑战:
- 非确定性输出 - 同样的输入,Agent可能给出不同回答
- 工具调用变化 - Agent可能选择不同的工具组合
- 外部依赖 - API、网页、数据库都可能变化
- 成本问题 - 每次测试都要消耗Token
测试金字塔
E2E测试
少量
集成测试
适量
单元测试
大量
第一层:单元测试
测试Agent的单个能力——工具调用、格式输出、意图识别:
# tests/unit/tool_calling.test.yaml
name: "工具调用测试"
description: "验证Agent正确选择和调用工具"
test_cases:
- name: "搜索请求正确调用web_search"
input: "帮我搜索OpenClaw最新版本"
expected:
tool_called: "web_search"
args_contains: "OpenClaw"
min_confidence: 0.8
- name: "文件操作正确调用read"
input: "读取config.yaml的内容"
expected:
tool_called: "read"
args_contains: "config.yaml"
- name: "模糊请求正确识别意图"
input: "那个谁说的那个事"
expected:
tool_called: null # 应该追问,不盲目调用
response_contains: ["请问", "具体", "哪"]
第二层:集成测试
测试工具组合和工作流:
# tests/integration/news_pipeline.test.yaml
name: "新闻流水线集成测试"
description: "验证搜索→提取→总结的完整流程"
setup:
- mock_web_search:
results: ["https://example.com/article1"]
- mock_web_fetch:
content: "这是一篇关于AI的最新文章..."
test_cases:
- name: "完整流水线执行"
input: "搜索今天的AI新闻并总结"
expected:
tools_called_in_order: ["web_search", "web_fetch"]
output_quality:
min_length: 50
contains_keywords: ["AI", "总结"]
no_contains: ["error", "failed"]
- name: "搜索无结果的处理"
setup:
- mock_web_search:
results: []
input: "搜索关于不存在的话题"
expected:
response_contains: ["没找到", "换个关键词", "尝试"]
第三层:E2E测试
测试完整用户场景:
# tests/e2e/user_scenario.test.yaml
name: "用户完整场景测试"
description: "模拟真实用户交互流程"
scenarios:
- name: "新用户引导流程"
steps:
1. input: "你好,你是谁?"
expect: self_introduction
2. input: "你能做什么?"
expect: capability_list
3. input: "帮我搜索最新的AI工具"
expect: search_with_results
4. input: "把结果发到飞书"
expect: action_confirmation
assertions:
total_turns: 4
no_hallucination: true
consistent_personality: true
- name: "错误恢复场景"
steps:
1. input: "读取一个不存在的文件"
expect: graceful_error
2. input: "那帮我创建这个文件"
expect: action_execution
assertions:
recovery_time: "< 3s"
no_confusion: true
自动化测试执行
# 运行所有测试
openclaw test run --all
# 运行特定测试套件
openclaw test run --suite unit
openclaw test run --suite integration
openclaw test run --suite e2e
# 运行单个测试
openclaw test run --file tests/unit/tool_calling.test.yaml
# 带覆盖率报告
openclaw test run --all --coverage --report html
# CI/CD集成
# .github/workflows/test.yml
# on: [push, pull_request]
# jobs:
# test:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - run: openclaw test run --all --junit
评估指标
# 测试评估配置
evaluation:
metrics:
- name: "任务完成率"
description: "Agent是否完成了用户要求的任务"
threshold: 0.85
- name: "工具选择准确率"
description: "Agent是否选择了正确的工具"
threshold: 0.9
- name: "响应质量"
description: "回答是否准确、完整、有用"
eval: "llm_judge" # 用LLM做裁判
judge_model: "gpt-4o"
- name: "安全性"
description: "是否拒绝了有害请求"
threshold: 1.0 # 必须100%通过
- name: "成本效率"
description: "完成任务的Token消耗是否合理"
max_tokens: 5000
💡 Pro Tip:用LLM做裁判(LLM-as-Judge)评估响应质量时,设置多个评判维度:准确性、完整性、有用性、安全性。不同维度的权重可以根据场景调整。
回归测试
每次修改Agent后,确保原有功能不受影响:
# 回归测试配置
regression:
baseline: "tests/baseline/golden_responses.json"
compare:
- metric: "tool_selection"
tolerance: 0 # 工具选择必须一致
- metric: "response_similarity"
tolerance: 0.15 # 响应相似度不低于85%
method: "embedding_cosine"
- metric: "task_completion"
tolerance: 0 # 任务完成状态必须一致
⚠️ 注意:Agent测试会消耗API Token。建议使用便宜的模型(如gpt-4o-mini)运行单元测试,只在E2E测试时使用生产模型。预计每次完整测试套件消耗$0.5-2。
最佳实践
- 测试先行 - 新功能先写测试用例
- Mock外部依赖 - 用模拟数据替代真实API调用
- 测试边界条件 - 空输入、超长输入、特殊字符
- 定期更新测试 - 随着功能迭代更新测试用例
- 自动化CI/CD - 每次提交自动运行测试
- 成本监控 - 追踪测试消耗的Token和费用