🧪 Agent Testing Framework

不测试的Agent就像不体检的代码——看着没问题,上线就翻车

"世界上有两种Agent开发者:一种在凌晨3点被叫起来修bug,另一种在写测试。前者很忙,后者睡得很香。选择权在你。"

为什么Agent需要测试?

传统软件测试是确定性的——输入A一定得到B。但Agent测试面临独特挑战:

测试金字塔

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。

最佳实践

  1. 测试先行 - 新功能先写测试用例
  2. Mock外部依赖 - 用模拟数据替代真实API调用
  3. 测试边界条件 - 空输入、超长输入、特殊字符
  4. 定期更新测试 - 随着功能迭代更新测试用例
  5. 自动化CI/CD - 每次提交自动运行测试
  6. 成本监控 - 追踪测试消耗的Token和费用

相关资源