共计 1578 个字符,预计需要花费 4 分钟才能阅读完成。
背景痛点:为什么我们需要重构 Agent 测评集?
在智能体开发实践中,测评集的质量直接决定了迭代效率。传统方案普遍存在三个致命缺陷:

- 覆盖不全:手工维护的测试用例往往只覆盖 happy path,边缘场景和异常输入经常遗漏
- 维护成本高:业务逻辑变更时需要同步修改大量硬编码的断言语句
- 性能瓶颈:随着用例数量增加,串行执行时间呈线性增长,夜间构建经常超时
以我们电商推荐 Agent 为例,原有测评集包含 200 个用例,完整运行需要 47 分钟,且无法检测出 30% 的边界条件错误。
技术方案设计
模块化架构
采用三层分离设计:
- 数据层:YAML 格式存储测试输入和预期输出
- 逻辑层:Python 实现核心验证算法
- 执行层:pytest 调度测试运行
# 架构示意图
class TestCase:
"""数据模型层"""
input: Dict[str, Any]
expected: Dict[str, Any]
weight: float
class Validator:
"""逻辑验证层"""
def compare(self, actual, expected) -> bool: ...
class Runner:
"""执行控制层"""
def run_concurrently(self, cases): ...
动态权重算法
根据历史通过率自动调整用例权重,优先执行高价值用例:
weight_t = (α * pass_rate) + (β * coverage) - (γ * exec_time)
其中:α=0.6, β=0.3, γ=0.1 为经验系数
pass_rate = 历史通过次数 / 总执行次数
核心代码实现
测试用例加载器
from typing import List, Dict, Any
import yaml
class TestLoader:
"""加载 YAML 格式的测试用例"""
def __init__(self, filepath: str):
self.filepath = filepath
def load_cases(self) -> List[Dict[str, Any]]:
with open(self.filepath) as f:
return yaml.safe_load(f)['test_cases']
多线程执行器
from concurrent.futures import ThreadPoolExecutor
class ConcurrentRunner:
"""并发执行测试用例"""
def __init__(self, max_workers=8):
self.executor = ThreadPoolExecutor(max_workers)
def run(self, func, cases):
futures = [self.executor.submit(func, case) for case in cases]
return [f.result() for f in futures]
性能优化实战
基准测试对比
| 方案 | 200 用例耗时 | 内存峰值 |
|---|---|---|
| 传统串行 | 47min | 2.1GB |
| 本方案(8 线程) | 9min | 1.3GB |
内存优化技巧
使用生成器替代列表存储用例:
def case_generator():
for i in range(100000):
yield generate_test_case(i) # 动态生成用例
避坑指南
- 并发问题:
- 为每个用例创建独立的 Agent 实例
-
使用线程局部存储 (threading.local) 保存状态
-
用例隔离:
- 每个用例的 setup/teardown 完全独立
-
数据库测试使用临时 schema
-
CI 集成:
- 设置超时熔断机制
- 失败用例自动重试 3 次
未来改进方向
- 模糊测试:结合 Hypothesis 库生成随机输入
- 覆盖率分析:使用 coverage.py 检测业务代码路径
- 智能调度:基于强化学习动态调整执行顺序
通过这套方案,我们成功将回归测试时间控制在 10 分钟以内,缺陷检出率提升 40%。关键在于坚持『用例即数据』的设计理念,将测试逻辑与业务实现彻底解耦。
正文完
