--- source_url: https://juejin.cn/post/7619990292557398068 tags: [juejin] ingested: 2026-05-14 sha256: a464dbcd5fd736b15761683ffc44b62e0944b66a6b5b8d49674b44911f0d4c8c --- # 03—AI Skill 测试用例设计完整指南:8 种类型 + 断言自检,覆盖率从 40% 到 90% 系列:SkillSentry · AI Skill 测评体系从零到一(三) 难度:进阶 适合读者:需要亲自设计测试用例的工程师 📌 一句话摘要:不知道怎么设计 AI Skill 测试用例?本文系统拆解 8 种用例类型、断言强度三级分类和 5 条断言自检规则,帮你把 Skill 测评覆盖率从 40% 提升到 90%。 ## 为什么用例设计是测评最难的部分 坏用例不会报错,只会让你误以为 Skill 没问题。两种后果: 1. **漏测**:Skill 有问题,但用例没覆盖到,测完以为没问题 2. **虚高**:断言写得太弱,没有 Skill 也会通过,通过率 100% 但实际质量很差 ## 测试金字塔在 AI Skill 的适配 | 软件测试层级 | AI Skill 对应 | 解决什么 | 发现不了什么 | |------------|-------------|---------|------------| | 单元测试 | 原子场景 | 单条规则是否正确 | 规则之间的组合冲突 | | 集成测试 | 业务逻辑/边界/鲁棒性 | 多规则组合是否正常 | 多轮对话的状态维护 | | E2E 测试 | 端到端用例 | 完整用户旅程 | 单条规则的具体失败原因 | ## 8 种用例类型详解 ### ① 正常路径(Happy Path) 目的:验证主流程在标准输入下能正常跑通。 设计要点: - 用真实用户会说的话,加背景信息(时间、场景) - 每个核心功能分支至少一个 - 发票文件路径等必要信息要在 prompt 里给出 ✅ 正例:「(当前用户:zhangsan)上周团队聚餐花了一笔,帮我做日常报销。发票文件路径:/home/.../invoice.pdf」 ### ② 原子场景(Atomic) 目的:每个用例只测一个功能点,失败时能精确定位问题。 设计原则:**一条规则 → 一个原子用例** ✅ 正例:「帮我报销上周的餐费(无发票)」→ 只测:无发票时 Skill 是否正确追问用户提供发票 ### ③ 业务逻辑(Business Logic) 目的:验证 SKILL.md 中定义的业务规则是否被正确执行。 从规则清单提取用例: | 规则类型 | 用例构造方式 | 断言方向 | |---------|------------|---------| | 条件判断(如果...则...) | 构造触发条件的场景 | 验证「则」的部分是否出现在输出中 | | 数值限制(上限/下限) | 构造刚好超过阈值的输入 | 验证是否触发了对应处理逻辑 | | 必填字段 | 构造缺少必填字段的输入 | 验证是否正确拒绝或追问 | | 禁止行为 | 构造触发禁止规则的输入 | 验证是否确实拒绝执行 | | 路由规则 | 构造不同方向的输入 | 验证各自走了正确的分支 | ### ④ 边界测试(Boundary) 目的:在极值和临界条件下,Skill 行为是否符合预期。 通用边界场景: - 数值类:值 = 限制值-1 / = 限制值 / = 限制值+1 - 时间类:有效期最后一天 / 有效期过后一天 - 输入类:空输入、极长输入、仅特殊字符 ### ⑤ 鲁棒性(Robustness) 目的:面对异常输入时,Skill 不崩溃也不输出错误结果。 | 异常类型 | 测试内容 | 期望行为 | |---------|---------|---------| | 信息不完整 | 只说意图,不提供发票 | 识别缺失,追问用户 | | 矛盾信息 | 说「日常报销」但发票项目名含「住宿」 | 暂停,询问用户确认 | | 无关输入 | 在报销过程中插入「今天天气怎么样」 | 忽略无关输入,继续原流程 | | 识别失败 | 发票 OCR 失败 + MCP 查验也失败 | 降级到手动提供 4 个字段,不崩溃 | ### ⑥ 负向测试(Negative) 目的:验证 Skill 知道「什么时候不该做什么」。 最有价值的场景:关键词命中但意图不符。 场景:用户问「住宿费报销有金额上限吗?」→ 询问政策≠报销,Skill 不应启动报销流程 断言:Skill 没有调用 queryExpenseApplier 或 saveExpenseDoc ### ⑦ 一致性(Consistency) 目的:同一语义的不同表达方式,关键输出字段应完全一致。 同一场景 3 个变体(正式/口语/极简): - 正式:「请帮我提交一份日常报销申请,金额 168 元,项目为餐饮服务」 - 口语:「帮我报个餐费,168 块,上周的发票」 - 极简:「168 餐费报销」 断言:三种表达下 expenseType 均为 1,fdExpenseSubject 均含「餐费」 ### ⑧ 端到端 E2E E2E 是 8 种类型中发现问题能力最强的一种,是唯一能抓住「规则冲突」与「状态污染」的手段。 与 Happy Path 的本质区别: | 维度 | Happy Path | E2E | |------|-----------|-----| | prompt 预设 | 已给出报销类型、发票路径、关键词 | 只有用户的原始意图,无任何预设 | | 对话轮次 | 通常单轮触发完整流程 | 多轮自然推进(6-10 轮) | | 发现的问题 | 单条规则执行是否正确 | 多条规则同时激活时是否打架 | ## 断言质量是测评可信度的基础 5 条自检规则: - □ **有判别力**:没有 Skill,这条断言也会通过吗?→ 如果会,改掉 - □ **可量化**:有明确的 pass/fail 标准,不依赖主观判断 - □ **原子性**:一条断言只测一件事 - □ **有来源**:必须能对应规则清单中的具体规则编号(如 R-05) - □ **覆盖负向**:不只测「应该有什么」,也测「不应该有什么」 好断言 vs 坏断言: | 坏断言 | 问题所在 | 改进后的好断言 | |--------|---------|--------------| | 「输出看起来不错」 | 主观,无法量化 | 「输出包含报销主题、金额、收款银行、详情链接四个字段」 | | 「输出非空」 | 无判别力,没有 Skill 也不会空 | 「输出包含以 expense.yourcompany.com 开头的详情链接」 | | 「Skill 正确处理了请求」 | 太模糊,无操作定义 | 「saveExpenseDoc 调用参数 docStatus=10,expenseType=1」 | | 「调用了 saveExpenseDoc」 | 只测有无,不测正确性 | 「saveExpenseDoc 在整个对话中只被调用一次」 | ## 断言强度分级 约 1/3 的断言是「存在性断言」——即使没有 Skill,模型也大概率通过。必须分级: | 强度 | 标识 | 定义 | 是否计入准入判断 | |------|------|------|---------------| | 精确断言 | ★ exact_match | 有具体可验证的字段值/计数/格式 | **是(核心)** | | 语义断言 | ◆ semantic | 需要语义理解判断 | 是(参考) | | 存在性断言 | ○ existence | 只验证有/无,无 Skill 也大概率通过 | **否** | 三个通过率:精确通过率(准入核心)→ 语义通过率(辅助参考)→ 综合通过率(兼容旧版) ## 用例数量参考 | 模式 | 总数 | 覆盖率目标 | |------|------|----------| | quick | 10-15 | ≥40% | | standard | 25-30 | ≥70% | | full | 40-50 | ≥90% | ⚠️ 用例数量是覆盖率目标的结果,不是输入。不要以为「凑够 25 个就算 standard 模式」。 ## 补充:用例清单不满意?支持手动调整 SkillSentry 支持多轮人工确认和修改: - 增加/删除/修改用例 prompt - 直接粘贴 JSON - 整批替换 删除保护:删除后低于最低要求会主动提醒。 字段完整性校验:缺少必填字段会被拦截并提示补全。