03—AI Skill 测试用例设计完整指南:8 种类型 + 断言自检,覆盖率从 40% 到 90%

7 阅读17分钟

AI Skill 测试用例设计完整指南:8 种类型 + 断言强度分级 + 断言自检,覆盖率从 40% 到 90%

系列:SkillSentry · AI Skill 测评体系从零到一(三)

难度:进阶

适合读者:需要亲自设计测试用例的工程师

📌 一句话摘要:不知道怎么设计 AI Skill 测试用例?本文系统拆解 8 种用例类型、断言强度三级分类和 5 条断言自检规则,帮你把 Skill 测评覆盖率从 40% 提升到 90%。

🏷️ 推荐标签:AI Skill测试用例 测试用例设计 LLM测试方法


为什么用例设计是测评最难的部分

AI Skill 测试用例设计之所以难,根本原因在于:坏用例不会报错,只会让你误以为 Skill 没问题。 测评工具可以自动执行用例,自动评审断言,自动生成报告。但用例本身,必须由理解业务的人来设计——或者由 AI 设计完后由业务人员审核。

用例设计得不好,有两种后果:

  1. 漏测:Skill 有问题,但用例没覆盖到,测完以为没问题
  2. 虚高:断言写得太弱,没有 Skill 也会通过,通过率 100% 但实际质量很差

这篇文章系统介绍 8 种用例类型,以及最重要的「断言质量自检」方法。

阅读建议:8 种类型中,①正常路径和②原子场景是基础,⑦一致性和⑧E2E 是最难设计也最有价值的——它们发现的问题是其他类型看不到的,建议重点阅读这两节。


测试金字塔在 AI Skill 的适配

传统软件测试的「测试金字塔」理论同样适用于 AI Skill,三层测试各自覆盖不同的问题域,缺一不可。测试金字塔由 Mike Cohn 提出,Martin Fowler 系统化推广:单元测试最多,集成测试次之,E2E 最少。AI Skill 的测试分层与之对应:

软件测试层级AI Skill 对应解决什么发现不了什么
单元测试原子场景单条规则是否正确规则之间的组合冲突
集成测试业务逻辑 / 边界 / 鲁棒性多规则组合是否正常多轮对话的状态维护
E2E 测试端到端用例完整用户旅程单条规则的具体失败原因

三层都不可替代——它们发现的问题类型完全不同。


8 种用例类型详解

① 正常路径(Happy Path)

目的:验证主流程在标准输入下能正常跑通。

设计要点

  • 用真实用户会说的话,加背景信息(时间、场景)
  • 每个核心功能分支(如日常报销 / 差旅报销)至少一个
  • 发票文件路径等必要信息要在 prompt 里给出

反例 vs 正例

❌ 反例:「请使用报销功能帮我报销」
   → 没有真实用户这样说,且缺少所有必要信息

✅ 正例:(当前用户:zhangsan)上周团队聚餐花了一笔,帮我做日常报销。
         发票文件路径:/home/.../invoice.pdf
   → 有用户身份、有场景描述、有发票,Skill 可以直接执行

识别方法:从 SKILL.md 找「用户的核心诉求 + 标准处理流程」,构造满足所有前置条件的 prompt。


② 原子场景(Atomic)

目的:每个用例只测一个功能点,失败时能精确定位问题。

设计原则:一条规则 → 一个原子用例

反例 vs 正例

❌ 反例:帮我完成日常报销,然后检查发票是否合规,最后告知我超标情况
   → 测了三件事,任何一处失败都无法定位

✅ 正例:帮我报销上周的餐费(无发票)
   → 只测:无发票时 Skill 是否正确追问用户提供发票

③ 业务逻辑(Business Logic)

业务逻辑测试是 8 种类型里最重要也最容易被忽视的——技术测试只能验证「输出了什么」,只有业务逻辑测试才能验证「输出的对不对」。

目的:验证 SKILL.md 中定义的业务规则是否被正确执行。

「技术测试只能验证『输出了什么』,业务逻辑测试才能验证『输出的对不对』。」

从规则清单提取用例的方法

规则类型用例构造方式断言方向
条件判断(如果...则...)构造触发条件的场景验证「则」的部分是否出现在输出中
数值限制(上限/下限)构造刚好超过阈值的输入验证是否触发了对应处理逻辑
必填字段构造缺少必填字段的输入验证是否正确拒绝或追问
禁止行为构造触发禁止规则的输入验证是否确实拒绝执行
路由规则构造不同方向的输入验证各自走了正确的分支

业务逻辑用例示例

规则:saveExpenseDoc 成功后严禁再次调用(防重复提交)
↓
用例 prompt:(当前用户:zhangsan)帮我报销这张发票。
             发票文件路径:.../invoice.pdf
             (Skill 完成后)再帮我报一次同一张发票
↓
断言:整个对话中 saveExpenseDoc 只被调用一次;
      第二次请求时 Skill 拒绝重复提交并提供已有详情链接

④ 边界测试(Boundary)

目的:在极值和临界条件下,Skill 行为是否符合预期。

通用边界场景

数值类:值 = 限制值-1(刚好不触发)
        值 = 限制值(刚好触发)
        值 = 限制值+1(超过阈值)
时间类:有效期最后一天 / 有效期过后一天
输入类:空输入、极长输入、仅特殊字符

em-reimbursement-v3 的边界例子

发票金额 = 4999  不触发大额警告(⚠ 发票金额较大)
发票金额 = 5000  触发大额警告
发票金额 = 5001  触发大额警告

断言:金额  5000 时,最终输出的风险项清单包含「发票金额较大,请确认」
     金额 < 5000 时,风险项清单不包含该条目

⑤ 鲁棒性(Robustness)

目的:面对异常输入时,Skill 不崩溃也不输出错误结果。

测试场景

异常类型测试内容期望行为
信息不完整只说意图,不提供发票识别缺失,追问用户
矛盾信息说「日常报销」但发票项目名含「住宿」暂停,询问用户确认
无关输入在报销过程中插入「今天天气怎么样」忽略无关输入,继续原流程
识别失败发票 OCR 失败 + MCP 查验也失败降级到手动提供 4 个字段,不崩溃

em-reimbursement-v3 的鲁棒性例子

场景:本地识别失败 + checkInvoice 也失败
期望:不崩溃,格式化询问用户手动提供 4 个字段(发票号/日期/金额/项目名)
断言:Skill 输出了 4 字段追问格式;未输出「报销完成」或「草稿已保存」

⑥ 负向测试(Negative)

目的:验证 Skill 知道「什么时候不该做什么」。

最有价值的场景:关键词命中但意图不符

场景 1:用户问「住宿费报销有金额上限吗?」
期望:询问政策≠报销,Skill 不应该启动报销流程
断言:Skill 没有调用 queryExpenseApplier 或 saveExpenseDoc

场景 2:用户说「我的报销单审批通过了吗?」
期望:查状态≠创建报销,Skill 不应该进入报销创建流程
断言:Skill 没有发起新的报销草稿

⑦ 一致性(Consistency)

目的:同一语义的不同表达方式,关键输出字段应完全一致。

设计要点:同一场景设计 3 个变体,表达方式有明显差异(正式 / 口语 / 极简)。

变体 1(正式):「请帮我提交一份日常报销申请,金额 168 元,项目为餐饮服务」
变体 2(口语):「帮我报个餐费,168 块,上周的发票」
变体 3(极简):「168 餐费报销」

一致性断言:
  三种表达下 expenseType 均为 1(日常报销)→ ✅ 一致
  三种表达下 fdExpenseSubject 均含「餐费」→ ✅ 一致
  三种表达下 fdApplyMoney 均为 168.00 → ✅ 一致(如有发票支撑)

⑧ 端到端 E2E

E2E 是 8 种 AI Skill 测试用例类型中发现问题能力最强的一种,也是唯一能抓住「规则冲突」与「状态污染」的手段。 验证完整多轮用户旅程,发现「规则单独正确但组合时打架」的问题。

E2E 是发现「规则冲突」与「状态污染」的唯一手段。

单条规则单独测,往往都能通过。但多条规则在同一次对话中同时激活,就可能互相干扰——一条规则的判断结果污染了下一条规则所依赖的上下文状态,最终输出完全错误。这种「合并后打架」的深层逻辑错误,只有 E2E 这种「全旅程模拟」才能抓到。

E2E 是 8 种类型中最难设计也最有价值的。它发现的问题类型在其他 7 种用例中完全看不到。

与 Happy Path 的本质区别

维度Happy PathE2E
prompt 预设已给出报销类型、发票路径、关键词只有用户的原始意图,无任何预设
对话轮次通常单轮触发完整流程多轮自然推进(6-10 轮)
发现的问题单条规则执行是否正确多条规则同时激活时是否打架

E2E prompt 格式示例(以报销为例):

[用户轮1] 上周花了钱,帮我处理一下
          ↑ 意图模糊,无类型、无发票

[Skill轮1] 预期:追问日常还是差旅

[用户轮2] 日常

[Skill轮2] 预期:追问提供发票

[用户轮3] 这是发票
          发票文件路径:/home/.../invoice.pdf
          (该发票项目名含「住宿」关键词)

[Skill轮3] 预期:识别住宿类发票,暂停并询问用户确认

[用户轮4] 继续报销

[Skill轮4] 预期:继续流程,完成费用匹配,保存草稿

[用户轮5] 再帮我报一次
          预期:Skill 拒绝重复提交,给出已有草稿链接

E2E 的两类断言

  1. 全程一致性断言:saveExpenseDoc 只被调用一次;路由决策(日常/差旅)一旦确认不中途切换;第 3 轮触发的住宿风险项在最终输出的风险清单中有记录
  2. 端点结果断言:最终输出包含完整的报销主题、金额、收款账户、详情链接;链接中不含字面占位符 {fdId}

断言质量是测评可信度的基础

断言质量直接决定测评结论是否可信——断言写得太弱,通过率再高也没有意义,只是在自欺欺人。以下是 5 条自检规则:

5 条自检规则

□ 有判别力:没有 Skill,这条断言也会通过吗?→ 如果会,改掉
□ 可量化:有明确的 pass/fail 标准,不依赖主观判断
□ 原子性:一条断言只测一件事
□ 有来源:必须能对应规则清单中的具体规则编号(如 R-05)
□ 覆盖负向:不只测「应该有什么」,也测「不应该有什么」

好断言 vs 坏断言(对比表):

坏断言问题所在改进后的好断言
「输出看起来不错」主观,无法量化「输出包含报销主题、金额、收款银行、详情链接四个字段」
「输出非空」无判别力,没有 Skill 也不会空「输出包含以 expense.yourcompany.com 开头的详情链接」
「Skill 正确处理了请求」太模糊,无操作定义「saveExpenseDoc 调用参数 docStatus=10,expenseType=1」
「调用了 saveExpenseDoc」只测有无,不测正确性「saveExpenseDoc 在整个对话中只被调用一次」

断言强度分级:让通过率真正有意义

真实审计发现:断言集中大约 1/3 是「存在性断言」——即使没有 Skill,模型也大概率通过。这类断言混入通过率计算会虚高结论,掩盖真实质量。

每条断言必须标注 precision 强度级别

强度标识定义典型例子是否计入准入判断
精确断言★ exact_match有具体可验证的字段值/计数/格式docStatus="10" / saveExpenseDoc 调用 1 次是(核心)
语义断言◆ semantic需要语义理解判断报销主题描述清晰,包含目的地和时间是(参考)
存在性断言○ existence只验证有/无,无 Skill 也大概率通过输出非空 / 没有编造发票

三个通过率指标的含义

精确通过率(exact_match)  → 准入判断的核心依据,才是真实质量
语义通过率(semantic)     → 辅助参考
综合通过率(all)           → 兼容旧版,报告中标注构成比例

为什么 existence 断言不计入准入?

以「没有编造发票信息」为例:这条断言测的是模型基础能力(不无中生有),而非 Skill 的特有价值。对应的 Δ ≈ 0——加了 Skill 和没加 Skill 效果一样,说明这条规则不是 Skill 的核心贡献。把它计入准入,会稀释「Skill 真正做对了什么」的信号。

断言强度自检(额外加一条)

□ 强度核查:没有 Skill,这条断言会通过吗?
   → 是  → precision = existence,此条不计入准入判断,降权使用
   → 否  → precision = exact_match 或 semantic,可计入

报告中的展示效果

每条断言旁边会显示强度 badge(★精确 / ◆语义 / ○存在性);汇总卡片第一张变为「精确断言通过率」;卡片下方新增三级分解区,一眼看清通过率的真实构成。


用例数量参考

模式总数正常路径原子业务逻辑边界鲁棒性负向E2E
quick10-152关键规则各 12
standard25-303-4关键规则各 13-52-32-32-31
full40-503-4所有规则各 15-83-53-43-43

⚠️ 重要用例数量是覆盖率目标的结果,不是输入。 不要以为「凑够 25 个就算 standard 模式」——quick 覆盖 ≥40% 路径,standard ≥70%,full ≥90%。实际用例数由 AI 根据被测 Skill 的路径复杂度自动计算,表格中的数字是参考范围,复杂 Skill 可能需要更多。


补充:用例清单不满意?支持手动调整

AI 设计完用例后,会展示完整清单并用选择题让你确认:

📝 测评方案:standard 模式,共 26 个用例

| # | 用例名 | 类型 | 覆盖规则 |
|---|--------|------|---------|
| 1 | 日常报销:完整主流程 | 正常路径 | R-01, R-07 |
| 2 | ...                 | ...      | ...      |

→ 确认,开始执行
→ 需要修改

如果觉得用例设计不够,点「需要修改」,可以做以下任何调整:

操作示例说法
增加用例「增加一个测试住宿发票检测的用例,prompt 是……」
删除用例「删掉第 3 个,这个场景不需要测」
修改 prompt「把第 5 个用例的 prompt 改成更口语化的表达」
粘贴 JSON直接粘贴完整用例 JSON,SkillSentry 验证字段完整后写入
整批替换「去掉所有边界测试,换成 3 个我指定的负向场景」
嫌数量不够「用例太少了,再多设计几个鲁棒性场景」

每次调整完,SkillSentry 都会重新展示完整清单,支持多轮修改直到满意,再开始执行。

有两个保护机制:

  1. 删除保护:删除用例后如果总数低于当前模式的最低要求,SkillSentry 会主动提醒,而不是默默删掉
  2. 字段完整性校验:用户粘贴 JSON 时,缺少 display_nameexpectations 等必填字段会被拦截并逐一提示补全,不允许以不完整的用例写入

这个设计背后的逻辑是:AI 设计的用例是基于 SKILL.md 的规则推导出来的,覆盖的是「规则文档里存在的路径」。但你作为业务方,可能知道一些没有写进 SKILL.md 但线上真实存在的边缘场景(比如用户经常误触发的口语说法、某个接口偶发的特殊返回)。把这些场景手动补进用例,测评结论的可信度会显著提升。


下一篇,我们来拆解四层验证体系——为什么要这样设计,每一层分别解决什么问题。


FAQ:关于 AI Skill 测试用例,用户常问的问题

AI Skill 测试用例有哪几种类型?

AI Skill 测试用例共分 8 种类型:正常路径(Happy Path)、原子场景、业务逻辑、边界测试、鲁棒性、负向测试、一致性和端到端 E2E。这 8 种类型对应软件测试的单元、集成、E2E 三个层级,分别发现不同类型的问题,缺一不可。其中前两种是基础,E2E 和一致性是最难设计也最有价值的。

什么是端到端(E2E)测试,为什么是最有价值的类型?

E2E 测试是模拟完整用户旅程的多轮对话测试,通常包含 6-10 轮交互,从模糊意图出发,自然推进到任务完成。它是 8 种类型中最有价值的,因为它是唯一能发现「规则冲突」与「状态污染」的手段——单条规则单独测往往都能通过,但多条规则在同一次对话中同时激活时,可能互相干扰,这种深层逻辑错误只有 E2E 才能抓到。

怎样判断一条断言是否有判别力?

最简单的判断方法是问自己:「如果完全没有这个 Skill,这条断言还会通过吗?」如果答案是会,那这条断言就没有判别力,测了等于没测。有判别力的断言必须包含只有 Skill 正确执行才会出现的具体证据,比如「saveExpenseDoc 调用参数 docStatus=10,expenseType=1」,而不是「输出非空」或「Skill 正确处理了请求」这类空洞表述。

什么是断言强度分级,为什么通过率要分三个层级?

真实审计发现约 1/3 的断言是「存在性断言」(如「输出非空」「没有编造信息」),这类断言即使没有 Skill 也大概率通过,混入通过率计算会虚高结论。因此将断言分为三级:精确断言(★ exact_match,有具体可验证字段值)、语义断言(◆ semantic,需语义理解)、存在性断言(○ existence,只验证有无)。准入判断只看精确断言通过率,存在性断言单独展示供参考,不计入发布决策。

quick / standard / full 三种模式各适合什么场景?

quick 模式(10-15 个用例)适合快速验证 Skill 的主干功能是否跑通,覆盖率 ≥40%,适合 Skill 开发早期的冒烟测试。standard 模式(25-30 个用例)覆盖率 ≥70%,适合正式发布前的回归测试。full 模式(40-50 个用例)覆盖率 ≥90%,适合对质量要求极高的关键业务 Skill。需要注意的是,实际用例数由 AI 根据 Skill 的路径复杂度自动计算,这里的数字只是参考范围。

为什么 AI 设计的用例还需要人工调整?

AI 设计用例的依据是 SKILL.md 的规则文档,因此只能覆盖「文档里存在的路径」。但业务方往往知道一些没有写进文档、却在线上真实发生的边缘场景——比如用户经常使用的特殊口语说法、某个接口偶发的异常返回、或某类发票的特殊处理逻辑。把这些场景手动补进用例清单,测评结论的可信度会显著提升。SkillSentry 支持多轮修改,直到你对用例清单满意为止。