AI功能测试避坑指南:90%的测试工程师都在犯的错误
还在用
assert actual <span class="wx-em-red"> expected测 AI?你的测试基本等于没测。
0. 写在前面:一个踩坑故事
2025 年底,我带团队给一个金融 AI 客服系统做质量保障。团队 5 个测试工程师,全是传统 Web 测试出身,经验最少的也有 4 年。我们用了最标准的测试流程:200 条测试用例、每条固定预期答案、自动化脚本逐条比对。测试通过率 92%,上线。
结果上线第一周,用户投诉率 15%。
我们懵了。92% 通过率的产品,用户说不准。后来逐条排查投诉记录,发现一个反直觉的事实:测试标记为"通过"的用例,用户觉得不准;测试标记为"失败"的用例,用户反而觉得没问题。
问题出在哪?出在我们还在用测 Web 页面的方式测 AI。今天这篇文章,就是当年那个坑的完整复盘。
1. 概念讲解
我在带团队做 AI 系统质量保障的时候,见过最多的问题就是:测试工程师拿着传统 Web 测试的经验直接套在 AI 系统上,结果测出来的东西全是假的。
传统功能测试的核心假设是确定性。你给系统输入 "2+2",系统必须返回 "4"。如果返回 "5",那就是 Bug。这个逻辑在天文学、金融学、电商交易系统里完全成立。但放在 AI 系统上,这个逻辑是致命错误。
为什么?因为 AI 系统的核心特征是概率性。同一个问题 "帮我写一封邮件拒绝这个邀请",第一次回答可能是 "尊敬的XXX,很抱歉...",第二次可能是 "您好,感谢邀请,但我..."。两次回答字面不同,但质量可能完全一样高。如果你用 assert actual </span> expected 去测,两次都会被判为 "失败"——因为第二次和第一次的输出不一样。
这不是 AI 的 Bug,这是 AI 的设计特性。自回归语言模型在每一步生成都从概率分布中采样,多样性是能力,不是缺陷。
AI功能测试不是"更难的测试",而是完全不同的测试类型。你需要同时掌握传统测试的工程能力、统计学的度量能力、产品思维的用户视角。
不做这个认知转换,你后面做的一切都是错的。
1.5. 传统功能测试 vs AI功能测试:8 个维度对比
光讲概念不够直观,下面这张表格把两种测试方式在 8 个关键维度上的差异列清楚。建议先收藏,后面讲到具体方法时可以回来对照。
| 对比维度 | 传统功能测试 | AI功能测试 |
|---|---|---|
| 核心假设 | 确定性:相同输入 → 相同输出 | 概率性:相同输入 → 质量相近的不同输出 |
| 断言方式 | 精确匹配(assert actual <span class="wx-em-red"> expected) | 范围判定(assert score > threshold) |
| 测试数据 | 手工构造边界值、等价类 | 真实用户日志 + 对抗样本 + 黄金数据集 |
| 自动化率 | 可做到 90%+ | 合理范围 60-80%(基于我们团队 3 个 AI 项目的实际数据) |
| 缺陷判定 | 非黑即白:通过 / 不通过 | 灰度评分:质量分数 + 人工复核 |
| 回归策略 | 全量回归,每次变更跑全部用例 | 分层回归:硬性验证全跑 + 质量度量抽样 + 用户体验抽检 |
| 测试环境 | 隔离环境,数据可造 | 隔离环境,但数据必须来自真实分布(造的数据会失真) |
| 团队技能 | 测试理论 + 自动化框架 | 测试理论 + 统计学 + 产品思维 + LLM 工具链 |
关键结论: AI功能测试不是"传统测试的升级版",而是"另一个物种"。你需要的不是更多测试用例,而是完全不同的测试思维。
2. 核心方法论
AI功能测试的方法论建立在一个三层验证模型上:
- 最底层:硬性验证。格式对不对、类型对不对、结构对不对。这部分是确定性的,可以 100% 自动化。比如 JSON 输出是否符合 Schema、工具调用参数是否完整。
- 中间层:质量度量。准确性、相关性、完整性。这部分是概率性的,需要用 LLM-as-a-Judge 或统计指标来评分。比如回答是否覆盖了问题的各个方面。
- 最顶层:用户体验。主观感受——"这个回答对我有帮助吗?"这部分必须靠人工抽检或用户反馈信号。
为什么要分层? 因为不同层的自动化率完全不同。硬性验证可以 100% 自动化,质量度量可以做到 60-80% 自动化,用户体验只能做到 10-20% 自动化。如果你试图用一套方法覆盖所有层,要么自动化率极低,要么漏掉大量问题。
用一张图来看更清楚:
graph TD
A[用户体验层<br/>自动化率 10-20%<br/>人工抽检 + 用户反馈] --> B[质量度量层<br/>自动化率 60-80%<br/>LLM-as-a-Judge + 统计指标]
B --> C[硬性验证层<br/>自动化率 100%<br/>Schema 校验 + 类型检查]
style A fill:#ff9999,stroke:#cc0000,color:#000
style B fill:#ffcc66,stroke:#cc7700,color:#000
style C fill:#66bb6a,stroke:#2e7d32,color:#fff
图中颜色从绿到红,代表自动化率从高到低。你的测试策略应该是:底层全自动化、中层半自动化、顶层人工兜底。
具体到测试策略上,你需要做三件事:
- 建立分层断言体系。对硬性验证用精确断言(
assert json.is_valid()),对质量度量用模糊断言(assert score > 0.85),对用户体验用抽样检查。 - 维护黄金测试集。一套经过人工验证的高质量问答对,每次变更(模型、Prompt、代码)后自动回归。这是你的质量基线。
- 设置合理的自动化率目标。AI功能测试的合理自动化率是 60-80%,不是 100%。剩下的 20-40% 必须人工参与。
3. 实战案例
场景:某金融 AI 客服系统的功能测试
前置条件: 系统是一个基于 GPT-4o 的金融客服 AI,回答用户关于理财产品、账户查询、转账等问题。
问题: 上线前测试团队用传统方法做了 200 条测试用例,每条都有固定的预期答案。上线后用户投诉率高达 15%——用户说"回答不准确"。
根因分析: 测试团队的问题在于用字面匹配代替了质量评估。比如测试用例 "请介绍我们的稳健型理财产品",预期答案是 "稳健型理财产品年化收益率3.5%,风险等级R2..."。但 AI 实际回答 "我们的稳健型理财年化约3.5%,属于低风险产品..."。字面不匹配,测试标记为失败。但用户实际体验中,这个回答是完全合格的。
反过来,有些字面匹配的测试通过了,但用户投诉——比如 AI 回答了一个字面正确但事实错误的收益率(把 3.5% 说成了 5%),因为测试用例的预期答案本身就是错的。
解决方案:
- 将 200 条测试用例重新分类:40 条硬性验证(格式、类型),120 条质量度量(准确性、相关性),40 条用户体验(人工抽检)。
- 对质量度量类用例,引入 LLM-as-a-Judge 评分,阈值设为 0.85。
- 对用户体验类用例,每周随机抽检 20 条,人工评分。
- 重新上线后,投诉率从 15% 降到 3%。
4. 代码示例
下面是一个分层验证的测试框架核心代码:
import json
import jsonschema
from bert_score import BERTScorer
# 初始化 BERTScore 评分器(用于语义相似度评估)
scorer = BERTScorer(lang="zh", rescale_with_baseline=True)
def layered_test(prompt, response, golden_criteria):
"""
分层功能测试:硬性验证 → 质量度量 → 用户体验
Args:
prompt: 用户输入
response: AI 回答
golden_criteria: 黄金标准(包含各层验证条件)
"""
results = {}
score = None # 初始化 score,避免后续引用未定义变量
# 第一层:硬性验证(确定性,100%自动化)
if golden_criteria.get("requires_json"):
try:
jsonschema.validate(json.loads(response), golden_criteria["json_schema"])
results["format"] = "PASS"
except (json.JSONDecodeError, jsonschema.ValidationError):
results["format"] = "FAIL"
return results # 格式错了,不用测质量
# 第二层:质量度量(概率性,LLM-as-a-Judge)
if golden_criteria.get("quality_threshold"):
score = llm_judge_score(
question=prompt,
answer=response,
reference=golden_criteria["reference_points"]
)
results["quality"] = "PASS" if score >= golden_criteria["quality_threshold"] else "FAIL"
# 第三层:用户体验(人工抽检,标记需要人工复核的)
if score is not None and score < 0.7: # 质量分数较低,需要人工确认
results["needs_human_review"] = True
return results
5. 注意事项和常见坑
- 别把多样性当 Bug。 AI 的每次回答不同是正常的,你要测的是"质量范围"而不是"固定答案"。用多次采样 + 统计判定代替单次精确匹配。
- 黄金数据集的质量决定了你测试的上限。 如果你的黄金数据集中有 10% 的标注错误,那你的测试基准就是错的。定期审查和更新黄金数据集,每季度至少一次。
- 别追求 100% 自动化。 AI功能测试的合理自动化率是 60-80%。剩下的必须人工参与——创意写作、用户体验评估、安全相关测试,这些靠机器搞不定。
- 测试环境要和生产环境隔离。 别在生产环境跑测试,别用生产数据做测试集。数据污染会导致你的测试结果完全失真。
- temperature 设置要固定。 测试时把 temperature 设为 0 或一个固定值,否则每次运行的结果不可比。上线前再做一轮高 temperature 的多样性测试。
- 别忽略 Token 消耗成本。 LLM-as-a-Judge 本身也要调 API,大规模测试时 Token 消耗惊人。我们的经验是:先用轻量指标(如 BERTScore)做初筛,再用 LLM Judge 做精评,可以省 60% 的 API 费用。
- 注意模型版本漂移。 同一个 Prompt,GPT-4o 2024-05 和 GPT-4o 2024-08 的输出可能不同。每次模型升级都要重新回归黄金数据集,不要假设"新版一定比旧版好"。
5.5. 常用工具一览
| 工具 | 用途 | 适用场景 |
|---|---|---|
| BERTScore | 语义相似度评分 | 快速初筛,无需 API 调用 |
| Rouge/L | 文本重叠度指标 | 摘要、翻译类任务 |
| LLM-as-a-Judge | 多维度质量评分 | 准确性、相关性、完整性 |
| Promptfoo | 开源 Prompt 测试框架 | 多模型对比、批量测试 |
| DeepEval | LLM 测试框架 | 集成 CI/CD 的自动化测试 |
| RAGAS | RAG 系统专用评测 | 检索质量 + 生成质量联合评估 |
工具选择原则:能本地算的不用 API,能粗筛的不一上来就精评。把贵的资源用在刀刃上。
6. 总结与思考
AI功能测试不是"更难的传统测试",而是"完全不同的测试类型"。你的断言方式、评测方法、自动化策略,全部要重新设计。
【思考题】 你现在的团队在测 AI 系统时,还在用 assert actual </span> expected 的方式吗?如果有,最大的痛点是什么?欢迎在评论区分享你的经历。
关键词: AI功能测试、传统功能测试、LLM测试、AI测试框架、LLM-as-a-Judge、BERTScore、黄金数据集、自动化测试、AI质量保障