乐于分享
好东西不私藏

【AI测试功能1】还在用 assert 测 AI?你的测试基本等于没测

【AI测试功能1】还在用 assert 测 AI?你的测试基本等于没测

这是AI测试功能系列的第1篇,整个系列会更60篇

92% 通过率的产品,上线第一周投诉率 15%。问题出在哪?


2025 年底,我带团队给一个金融 AI 客服系统做质量保障。

团队 5 个测试工程师,全是传统 Web 测试出身,经验最少的也有 4 年。我们用了最标准的测试流程:

200 条测试用例、每条固定预期答案、自动化脚本逐条比对。

测试通过率 92%。上线。

结果上线第一周,用户投诉率 15%。

我们懵了。92% 通过率的产品,用户说不准。后来逐条排查投诉记录,发现一个反直觉的事实:

测试标记为”通过”的用例,用户觉得不准;测试标记为”失败”的用例,用户反而觉得没问题。

问题出在哪?

出在我们还在用测 Web 页面的方式测 AI。

今天这篇文章,就是当年那个坑的完整复盘。如果你也在做 AI 系统的质量保障,这篇文章能帮你少走至少半年的弯路。


你现在的测试方式,可能是错的

我在带团队做 AI 系统质量保障的时候,见过最多的问题就是:

测试工程师拿着传统 Web 测试的经验直接套在 AI 系统上,结果测出来的东西全是假的。

传统功能测试的核心假设是确定性

你给系统输入 “2+2″,系统必须返回 “4”。如果返回 “5”,那就是 Bug。这个逻辑在天文学、金融学、电商交易系统里完全成立。

但放在 AI 系统上,这个逻辑是致命错误

为什么?

因为 AI 系统的核心特征是概率性

同一个问题 “帮我写一封邮件拒绝这个邀请”,第一次回答可能是 “尊敬的XXX,很抱歉…”,第二次可能是 “您好,感谢邀请,但我…”。

两次回答字面不同,但质量可能完全一样高

如果你用 assert actual <span class="wx-em-red"> expected 去测,两次都会被判为 “失败”——因为第二次和第一次的输出不一样。

这不是 AI 的 Bug,这是 AI 的设计特性。自回归语言模型在每一步生成都从概率分布中采样,多样性是能力,不是缺陷

AI功能测试不是”更难的测试”,而是完全不同的测试类型。你需要同时掌握传统测试的工程能力、统计学的度量能力、产品思维的用户视角。

不做这个认知转换,你后面做的一切都是错的。


传统功能测试 vs AI功能测试:8 个维度对比

光讲概念不够直观,下面这张表格把两种测试方式在 8 个关键维度上的差异列清楚。

建议先收藏,后面讲到具体方法时可以回来对照。

对比维度
传统功能测试
AI功能测试
核心假设
确定性:相同输入 → 相同输出
概率性:相同输入 → 质量相近的不同输出
断言方式
精确匹配(assert actual </span> expected
范围判定(assert score > threshold
测试数据
手工构造边界值、等价类
真实用户日志 + 对抗样本 + 黄金数据集
自动化率
可做到 90%+
合理范围 60-80%(基于我们团队 3 个 AI 项目的实际数据)
缺陷判定
非黑即白:通过 / 不通过
灰度评分:质量分数 + 人工复核
回归策略
全量回归,每次变更跑全部用例
分层回归:硬性验证全跑 + 质量度量抽样 + 用户体验抽检
测试环境
隔离环境,数据可造
隔离环境,但数据必须来自真实分布(造的数据会失真)
团队技能
测试理论 + 自动化框架
测试理论 + 统计学 + 产品思维 + LLM 工具链

关键结论: AI功能测试不是”传统测试的升级版”,而是”另一个物种”。你需要的不是更多测试用例,而是完全不同的测试思维。


三层验证模型:AI功能测试的正确姿势

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

图中颜色从绿到红,代表自动化率从高到低。你的测试策略应该是:底层全自动化、中层半自动化、顶层人工兜底

具体到测试策略上,你需要做三件事:

  1. 建立分层断言体系
    。对硬性验证用精确断言(assert json.is_valid()),对质量度量用模糊断言(assert score > 0.85),对用户体验用抽样检查。
  2. 维护黄金测试集
    。一套经过人工验证的高质量问答对,每次变更(模型、Prompt、代码)后自动回归。这是你的质量基线。
  3. 设置合理的自动化率目标
    。AI功能测试的合理自动化率是 60-80%,不是 100%。剩下的 20-40% 必须人工参与。

实战案例:投诉率从 15% 降到 3%

场景:某金融 AI 客服系统的功能测试

前置条件: 系统是一个基于 GPT-4o 的金融客服 AI,回答用户关于理财产品、账户查询、转账等问题。

问题: 上线前测试团队用传统方法做了 200 条测试用例,每条都有固定的预期答案。上线后用户投诉率高达 15%——用户说”回答不准确”。

根因分析: 测试团队的问题在于用字面匹配代替了质量评估

比如测试用例 “请介绍我们的稳健型理财产品”,预期答案是 “稳健型理财产品年化收益率3.5%,风险等级R2…”。但 AI 实际回答 “我们的稳健型理财年化约3.5%,属于低风险产品…”。

字面不匹配,测试标记为失败。但用户实际体验中,这个回答是完全合格的。

反过来,有些字面匹配的测试通过了,但用户投诉——比如 AI 回答了一个字面正确但事实错误的收益率(把 3.5% 说成了 5%),因为测试用例的预期答案本身就是错的。

解决方案:

  1. 将 200 条测试用例重新分类:40 条硬性验证(格式、类型),120 条质量度量(准确性、相关性),40 条用户体验(人工抽检)。
  2. 对质量度量类用例,引入 LLM-as-a-Judge 评分,阈值设为 0.85。
  3. 对用户体验类用例,每周随机抽检 20 条,人工评分。
  4. 重新上线后,投诉率从 15% 降到 3%。

代码示例:分层验证框架

下面是一个分层验证的测试框架核心代码:

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

7 个常见坑,踩中一个就白干

坑 1:别把多样性当 Bug

AI 的每次回答不同是正常的,你要测的是”质量范围”而不是”固定答案”。用多次采样 + 统计判定代替单次精确匹配。

坑 2:黄金数据集的质量决定了你测试的上限

如果你的黄金数据集中有 10% 的标注错误,那你的测试基准就是错的。定期审查和更新黄金数据集,每季度至少一次。

坑 3:别追求 100% 自动化

AI功能测试的合理自动化率是 60-80%。剩下的必须人工参与——创意写作、用户体验评估、安全相关测试,这些靠机器搞不定。

坑 4:测试环境要和生产环境隔离

别在生产环境跑测试,别用生产数据做测试集。数据污染会导致你的测试结果完全失真。

坑 5:temperature 设置要固定

测试时把 temperature 设为 0 或一个固定值,否则每次运行的结果不可比。上线前再做一轮高 temperature 的多样性测试。

坑 6:别忽略 Token 消耗成本

LLM-as-a-Judge 本身也要调 API,大规模测试时 Token 消耗惊人。我们的经验是:先用轻量指标(如 BERTScore)做初筛,再用 LLM Judge 做精评,可以省 60% 的 API 费用。

坑 7:注意模型版本漂移

同一个 Prompt,GPT-4o 2024-05 和 GPT-4o 2024-08 的输出可能不同。每次模型升级都要重新回归黄金数据集,不要假设”新版一定比旧版好”。


常用工具一览

工具
用途
适用场景
BERTScore
语义相似度评分
快速初筛,无需 API 调用
Rouge/L
文本重叠度指标
摘要、翻译类任务
LLM-as-a-Judge
多维度质量评分
准确性、相关性、完整性
Promptfoo
开源 Prompt 测试框架
多模型对比、批量测试
DeepEval
LLM 测试框架
集成 CI/CD 的自动化测试
RAGAS
RAG 系统专用评测
检索质量 + 生成质量联合评估

工具选择原则:能本地算的不用 API,能粗筛的不一上来就精评。把贵的资源用在刀刃上。


写在最后

AI功能测试不是”更难的传统测试”,而是”完全不同的测试类型”。你的断言方式、评测方法、自动化策略,全部要重新设计。

你现在的团队在测 AI 系统时,还在用 assert actual == expected 的方式吗?

如果有,最大的痛点是什么?欢迎在评论区分享你的经历。