上个月,一个测试组长跟我吐槽了一件事。
他们团队有一份《用例编写规范》,写在 Confluence 上,三十多页。里面规定了用例编号格式、前置条件怎么写、断言必须分几层、异常场景要覆盖哪些类型。
新来的测试同学入职第一周,组长把链接发给他,说“写用例之前先看一遍”。新人看了,但看一遍记不住,写出来的用例还是不合规。组长只能一条条批注:“编号格式不对”“断言太弱”“异常场景漏了鉴权”。
更麻烦的是AI。组长让Claude生成用例,生成出来的东西和规范完全不搭边——编号格式不一样,断言只有status_code == 200,异常场景只覆盖了参数缺失。
组长问我:“有没有办法让AI自动按我们的规范生成?”
我说:“你那份规范,现在只存在于Confluence里。AI读不到它。你得把它变成一个Claude Code能自动加载的Skill。 ”
一、为什么“有规范”不等于“AI会遵守”?
先搞清楚一件事:Claude Code每次进入项目,会自动读取.claude/skills/目录下的Skill。但它不会自动去Confluence上翻你那份三十页的规范。
你现在的状态是:规范存在,但没有被加载。
每次让AI生成用例,你要么手动把规范粘贴进对话框,要么口头补充几句“编号格式是XX”“断言要分三层”。粘贴的规范太长,AI抓不住重点;口头补充的规则不全,AI每次都漏。
规范没有被“翻译”成AI能执行的形式,所以它只对人有效,对AI无效。
SKILL.md要做的,不是把三十页规范原样复制进去,而是把它拆成两部分:AI每次生成都必须遵守的“硬规则”,和需要时才查的“参考模板”。
二、先拆规范:哪些是“硬规则”,哪些是“参考模板”?
打开你那份《用例编写规范》,把里面的内容分成两类。
硬规则:每次生成用例都必须遵守的、违反就是错的。比如:
用例编号格式:{模块}-{类型}-{序号},类型只能是FUNC/API/UI/PERF
断言必须分三层:协议层、数据层、业务层
异常场景必须覆盖:参数缺失、类型错误、鉴权失败、重复提交、边界值
每条用例必须标注优先级:P0/P1/P2
参考模板:需要时才查的、不影响“对不对”但影响“好不好”的。比如:
完整用例表格的示例
某个业务模块的特定规则(优惠券叠加、退款金额计算)
历史Bug模式清单
不同场景下的断言示例
拆分的意义:硬规则放进SKILL.md正文,每次生成都生效。参考模板放进references/目录,AI只在需要时才加载,不占用上下文。
三、手把手:六步把规范变成Skill
第一步:搭目录结构(2分钟)
在项目根目录创建Skill目录:
.claude/skills/test-case-standard/
├── SKILL.md
├── references/
│ ├── case-template.md
│ ├── assertion-examples.md
│ └── business-rules.md
└── scripts/
└── validate_cases.py
关键规则:SKILL.md文件名必须全大写。文件夹命名用kebab-case,比如test-case-standard。
第二步:写头信息——决定Claude什么时候自动加载(10分钟)
这是整个Skill最关键的字段。description决定了Claude在什么场景下自动加载这个Skill。
name: test-case-standard
description: 按照团队《用例编写规范》生成结构化测试用例。当用户提到“生成测试用例”“编写用例”“测试用例设计”“按规范写用例”时自动触发。
when_to_use: 用户需要生成或评审测试用例时使用。适用于功能测试、接口测试、回归测试的用例设计。
allowed-tools: Read, Write, Bash
description写得好不好的区别:
❌ 写“帮助生成测试用例”——Claude不知道什么时候该用,可能一直不加载
✅ 写“当用户提到生成测试用例、编写用例、测试用例设计时自动触发”——Claude一听到这些词就加载
when_to_use是补充说明,写清楚适用场景和不适用场景。比如“不适用于性能测试脚本生成”——这句话能防止Claude在错误的场景下加载这个Skill。
第三步:写正文——把“硬规则”变成AI能执行的指令(30分钟)
正文是Skill的“大脑”。不要写“规范要求断言要全面”这种模糊表述,要写AI能直接执行的具体规则。
任务
按照团队《用例编写规范》生成结构化测试用例。
硬规则(每次生成必须遵守,违反即无效)
用例编号格式
{模块缩写}-{类型}-{三位序号}
类型只能是:FUNC(功能)、API(接口)、UI(界面)、PERF(性能)
示例:ORDER-FUNC-001、PAY-API-012
断言分层(缺一不可)
- 协议层:HTTP状态码、Content-Type
- 数据层:业务code、关键字段存在性、字段类型
- 业务层:状态流转、金额计算、关联数据一致性
禁止只写 status_code == 200。禁止用“不为空”代替具体值校验。
异常场景(每类至少一条)
- 参数缺失(逐个必填参数)
- 参数类型错误
- 参数格式错误(手机号、邮箱、日期)
- 鉴权失败(无token、token过期、越权)
- 重复提交(幂等性)
- 边界值(最小值、最大值、刚好越界)
优先级标注
P0:核心流程阻断或资金损失
P1:主要功能异常,有替代方案
P2:边缘场景,不影响主流程
每条用例必须标注优先级,并在备注里写明判断依据。
执行步骤
步骤1:理解需求
读取用户提供的需求描述或测试地图,提取功能点、输入参数、业务规则。
步骤2:识别测试场景
按硬规则中的异常场景清单,逐项检查是否覆盖。
步骤3:生成用例
按以下表格格式输出:
| 用例编号 | 测试场景 | 前置条件 | 测试步骤 | 预期结果 | 断言层级 | 优先级 |
步骤4:自检
生成后检查:
- [ ] 编号格式是否符合 {模块}-{类型}-{序号}?
- [ ] 每条用例断言是否覆盖三层?
- [ ] 异常场景是否覆盖了6类?
- [ ] 每条用例是否标注了优先级和依据?
参考资料
- 用例模板和示例:references/case-template.md
- 断言写法示例:references/assertion-examples.md
- 业务规则库:references/business-rules.md
几个关键设计:
第一,硬规则要用“祈使句+具体值” 。不要写“编号要规范”,要写“编号格式是{模块}-{类型}-{序号},类型只能是FUNC/API/UI/PERF”。
第二,自检清单要可勾选。Claude生成完会对照清单检查,漏了会自己补。
第三,references只引用文件名,不展开内容。详细模板放在references/目录里,Claude只在需要时才去读。这是渐进式披露——平时只加载SKILL.md,需要时才加载参考文档,不浪费上下文。
第四步:写references——放“参考模板”,按需加载(20分钟)
references/目录放那些“不影响对不对,但影响好不好”的内容。
references/case-template.md:完整的用例表格示例,包含3-5条标准用例。Claude生成时可以参考这个示例的颗粒度。
references/assertion-examples.md:不同类型接口的断言示例。比如:
查询接口:状态码 + code + data数组非空 + 首元素字段类型
创建接口:状态码 + code + id非空 + 数据库记录存在
更新接口:状态码 + code + 字段值已变更 + 关联数据一致
references/business-rules.md:团队积累的业务规则清单。比如:
优惠券叠加规则:满减券和折扣券不能同时使用
退款金额:不能超过订单实付金额
库存扣减:并发下单时使用乐观锁
这些内容不要写进SKILL.md正文。正文超过500行,每次加载都会浪费大量Token。
第五步:写scripts——放“校验脚本”,让Claude自己检查(15分钟)
scripts/validate_cases.py的作用是:Claude生成用例后,调用这个脚本做机械校验。
!/usr/bin/env python3
"""校验用例是否符合规范"""
import re
import sys
import json
def validate(cases):
errors = []
id_pattern = re.compile(r'^[A-Z]+-(FUNC|API|UI|PERF)-\d{3}$')
for case in cases:
# 检查编号格式
ifnot id_pattern.match(case.get("id", "")):
errors.append(f"编号格式错误:{case.get('id')}")
# 检查断言层级
assertions = case.get("assertions", [])
levels = {a.get("level") for a in assertions}
for required in ["协议层", "数据层", "业务层"]:
if required notin levels:
errors.append(f"{case.get('id')} 缺少{required}断言")
# 检查优先级
if case.get("priority") notin ["P0", "P1", "P2"]:
errors.append(f"{case.get('id')} 优先级无效")
return errors
if name == "main":
cases = json.load(sys.stdin)
errors = validate(cases)
if errors:
print("\n".join(errors))
sys.exit(1)
print("校验通过")
在SKILL.md里引用这个脚本:
步骤5:机械校验
运行 python scripts/validate_cases.py 校验生成的用例,如果有错误,根据错误提示修正后重新校验。
脚本负责确定性检查(编号格式、断言层级、优先级值),Claude负责语义检查(业务规则是否覆盖、断言是否合理) 。两者分工,各管各的。
第六步:验证——用历史用例对比(30分钟)
Skill写好了,不要直接拿去用。先做一次验证。
方法:找10条你之前人工写的、符合规范的用例,让Claude用这个Skill重新生成一遍,对比两者的差异。
检查三件事:
编号格式是否一致?
断言层级是否覆盖了三层?
异常场景是否覆盖了6类?
不一致的地方,就是SKILL.md里没写清楚的地方。比如Claude生成的用例没有“重复提交”场景,说明你的异常场景清单里没写清楚“重复提交”具体怎么测。补进去,重新验证。
验证通过的标准:Claude生成的10条用例,和你人工写的10条,在格式和覆盖度上没有显著差异。
四、一个真实的对比
我们团队那个测试组长,花了一个下午把规范变成了Skill。第二周他给我看了数据:
指标
转化前
转化后
用例格式合规率
约60%
约95%
断言覆盖三层比例
约40%
约90%
异常场景覆盖率
约50%
约85%
人工批注修改时间
每条约3分钟
每条约30秒
最关键的变化:新人不用再“看一遍三十页规范再写”了。Claude自动加载Skill,生成的用例直接符合规范。组长只需要抽查,不需要逐条批注。
五、避坑指南
坑一:把三十页规范原样粘进SKILL.md。 正文超过500行,每次加载都浪费大量Token,而且AI抓不住重点。硬规则放正文,详细模板放references/。
坑二:description写得太空。 写“帮助写用例”等于没写。要写清楚触发条件:用户说什么话、什么场景下加载。
坑三:硬规则写成模糊表述。 “断言要全面”不是规则,“断言必须覆盖协议层、数据层、业务层”才是规则。AI不知道“全面”是什么意思。
坑四:写完不验证。 用历史用例跑一遍,对比差异。不一致的地方,就是你没写清楚的地方。
坑五:忘了让Skill自动加载。SKILL.md放在.claude/skills/下,Claude Code重启后自动识别。如果没生效,检查文件名是否全大写、文件夹是否用kebab-case、description是否写了触发词。
最后
你团队那份《用例编写规范》,不是没用,是“只对人有效”。
新人看一遍记不住,AI根本读不到。你每次口头补充的“编号格式是XX”“断言要分三层”,本质上是在手动加载规范。
把它写成Skill,等于把“手动加载”变成了“自动加载”。 Claude每次进入项目,自动读取规范;每次生成用例,自动按规范执行;每次生成完,自动跑校验脚本。
你那份规范,从“Confluence上的文档”,变成了“AI能执行的规则”。
规范还是那份规范。只是它现在会自己生效了。
本文部分内容参考了霍格沃兹测试开发学社整理的相关技术资料,主要涉及软件测试、自动化测试、测试开发及 AI 测试等内容,侧重测试实践、工具应用与工程经验整理。