1. 测试 Skill 从零搭建:为什么你的 AI 每次都在重复造轮子
先说结论:测试类 Skill 的本质,是把「一个资深测试工程师接到需求后怎么思考、怎么拆场景、怎么产出用例」这套隐性经验,固化成一个 AI 能自动加载的文件夹。它不是一个更长的 Prompt,而是带触发条件、带可执行脚本、带参考资料的能力单元。适合谁?适合每天在 Claude Code、Cline、Cursor 这类本地 AI 编码工具里反复输入同一套测试指令的人,尤其是测试开发、QA 负责人、以及想把团队测试规范沉淀下来的工程同学。
我见过太多人把测试流程写成一段超长 Prompt,粘在对话框里,换个会话就没了。下次开新项目,又得重新粘一遍,还得手动补上「记得覆盖边界值」「记得检查权限」。这不是 AI 不聪明,是你没给它一个稳定的「技能包」。Skill 的渐进式披露机制解决的就是这个问题:平时只加载每个 Skill 的名字和描述,大约一百来个 Token,等模型判断当前任务和某个 Skill 相关,才把完整正文拉进来;正文里再指向 references 目录的长文档,模型只在真正需要时才去读。于是你可以装几十个 Skill,上下文也不会炸。
这篇要做的,是一个「测试用例生成 + 断言校验」的完整 Skill,三步走:先写 SKILL.md 定义触发条件与输入输出,再用 scripts 封装可执行测试脚本,最后用 references 沉淀断言规范与样例数据。三步做完,再通过 TaoToken 的统一 Key 和 API 通道跑一次端到端验证,确认这个 Skill 在你的本地编码工具里真的能被触发、能调脚本、能出结果。下面每一步都给可复制的目录结构、模板和命令,你照着改名字就能用。
需要提前说清楚一个边界:Skill 管的是「模型该怎么做这件事」,MCP 管的是「模型能用什么工具」。两者是协作关系。你这个测试 Skill 里如果要连数据库查断言数据,那是 MCP 的活;Skill 负责规定「先查哪张表、比对哪些字段、失败怎么记录」。别把两者混为一谈,否则目录会越搭越乱。
2. TaoToken 前置准备:统一 Key 与 API 通道怎么配(含 base_url 设置)
在写 Skill 之前,先把模型调用通道理顺。原因很现实:Skill 里的 scripts 要跑测试脚本、要做断言校验,很多时候需要模型参与判断,比如让模型读一段响应体、判断断言是否合理。如果你的编码工具、脚本、验证请求各自用一套 Key,排障时会非常痛苦。TaoToken 的价值就在这里——一个统一 Key,走同一个 API 通道,工具侧和脚本侧共用,出问题只看一个地方。
先拿 Key。打开官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,注册后进控制台,在 API Keys 页面创建一个 Key。控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,API Keys 页面是 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。Key 只显示一次,复制到本地环境变量里,别硬编码进脚本。
API 基础地址统一用 https://taotoken.net/api ,注意这个地址不带任何查询参数,配置时原样填。模型对话的入口在 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite ,需要临时验证某个模型能不能通,直接在这里发一句话最快。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,参数细节以文档为准。
环境变量这样设,Linux/macOS 写进~/.zshrc或~/.bashrc,Windows 用系统环境变量:
export TAOTOKEN_API_KEY="sk-你的key" export TAOTOKEN_BASE_URL="https://taotoken.net/api"如果你用的是 Claude Code 这类工具,它读的是 Anthropic 兼容配置,需要把 Base URL 指向 TaoToken 的通道。参考配置片段如下,路径按你本机实际文件位置调整:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_AUTH_TOKEN": "sk-你的key", "ANTHROPIC_MODEL": "claude-sonnet-4-20250514" } }这里有个关键点必须讲透:Base URL、Key、Model ID 是三件套,缺一不可。很多人只改了 Base URL,Key 还是旧的,结果 401;或者 Key 对了,Model ID 写了个不存在的名字,报模型不存在。三件套要一起对齐。Model ID 以接入文档里列出的为准,别凭记忆写。
如果你用的是 Cline 这类支持 MCP 的工具,配置里同样要落三件套。Cline 的 MCP 配置走 JSON,形如:
{ "mcpServers": { "taotoken-test-helper": { "command": "npx", "args": ["-y", "@your-scope/test-mcp-server"], "env": { "TAOTOKEN_BASE_URL": "https://taotoken.net/api", "TAOTOKEN_API_KEY": "sk-你的key", "TAOTOKEN_MODEL": "claude-sonnet-4-20250514" } } } }注意,MCP 直连生产库是禁区,这里的 MCP server 只做测试辅助,比如读测试环境的样例数据、跑断言比对,不碰生产。长期做编码和 Agent 类任务的同学,可以看 Coding Plan 页面 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,把额度规划清楚再上量。
配完先别急着写 Skill,用一条 curl 确认通道通:
curl -s https://taotoken.net/api/v1/messages \ -H "x-api-key: $TAOTOKEN_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "max_tokens": 64, "messages": [{"role": "user", "content": "回复 ok"}] }'返回里有content数组、里面是文本,就说明通道正常。这一步过了,再进 Skill 目录搭建,否则后面所有报错你都会怀疑是 Skill 写错了。
3. 可复制配置:SKILL.md 模板 + scripts 脚本 + references 规范三件套
现在进正题。Skill 就是一个文件夹,必须有一个全大写的SKILL.md,文件夹名用 kebab-case,比如test-case-generator,别用空格和大写。放哪儿?项目级放.claude/skills/test-case-generator/,个人级放~/.claude/skills/test-case-generator/,同名时个人级优先。团队协作建议放项目级,跟着仓库走。
完整目录结构长这样,直接照抄改名字:
test-case-generator/ ├── SKILL.md ├── references/ │ ├── assertion-spec.md │ └── sample-data.json └── scripts/ ├── run_assertions.py └── format_cases.py3.1 SKILL.md 的 YAML 头与正文模板
SKILL.md分两段:YAML 头信息控制「什么时候触发」,Markdown 正文控制「具体怎么做」。头信息模板:
--- name: test-case-generator description: 根据功能描述或接口文档生成结构化测试用例,覆盖正常流程、异常场景、边界条件和权限校验,并调用脚本执行断言校验。当用户提到"生成测试用例""设计测试场景""补断言""测试覆盖"时触发。 when_to_use: 用户需要从需求文档、接口定义或功能描述产出测试用例,或需要对已有响应做断言校验时使用。 allowed-tools: Read, Write, Edit, Bash ---description是整个 Skill 里最重要的字段,模型靠它判断该不该加载。写「帮助测试」等于没写,要写清楚触发条件和适用阶段。allowed-tools里给了 Bash,是因为后面要跑 scripts,不给的话脚本调不起来。
正文部分给一个精简但可用的模板,控制在 500 行以内,超出的往 references 挪:
## 任务 根据用户提供的功能描述或接口文档,生成覆盖四类场景的测试用例,并对关键响应执行断言校验。 ## 执行步骤 ### 步骤1:解析输入 提取核心功能、输入参数与约束、业务规则、权限角色。信息缺失时标注"需确认",不臆造。 ### 步骤2:列场景 - 正常流程:至少 1 条完整 Happy Path - 异常场景:参数缺失、格式错误、业务规则违反、依赖超时 - 边界条件:数值上下界、空值、状态转换临界点 - 权限校验:未授权、越权、角色差异 ### 步骤3:生成用例 每条用例含:用例编号、测试场景、前置条件、测试步骤、预期结果、优先级。 ### 步骤4:执行断言 调用 `python scripts/run_assertions.py --input cases.json`,按 `references/assertion-spec.md` 的规范比对响应字段。 ### 步骤5:格式化输出 用 `python scripts/format_cases.py` 把结果转成 Markdown 表格。 ## 参考资料 - 断言规范:`references/assertion-spec.md` - 样例数据:`references/sample-data.json` ## 输出格式 Markdown 表格,列:用例编号 | 测试场景 | 前置条件 | 测试步骤 | 预期结果 | 优先级3.2 scripts 脚本:断言执行与格式化
scripts/run_assertions.py负责读用例、发请求、按规范比对。注意脚本里读的是环境变量,不硬编码 Key:
import json, os, sys, argparse, urllib.request BASE = os.environ.get("TAOTOKEN_BASE_URL", "https://taotoken.net/api") KEY = os.environ.get("TAOTOKEN_API_KEY", "") def check_field(resp, path, expect): cur = resp for p in path.split("."): cur = cur.get(p) if isinstance(cur, dict) else None return cur == expect, cur def main(): ap = argparse.ArgumentParser() ap.add_argument("--input", required=True) args = ap.parse_args() with open(args.input, encoding="utf-8") as f: cases = json.load(f) failed = 0 for c in cases: ok, actual = check_field(c["response"], c["assert_path"], c["expect"]) print(f'{c["id"]} {"PASS" if ok else "FAIL"} expect={c["expect"]} actual={actual}') failed += 0 if ok else 1 sys.exit(1 if failed else 0) if __name__ == "__main__": main()scripts/format_cases.py把 JSON 结果转 Markdown 表格,逻辑简单,读文件、拼表头、逐行输出即可。两个脚本都只依赖标准库,避免在别人机器上装依赖装到崩溃。
3.3 references 规范与样例数据
references/assertion-spec.md沉淀断言规范,比如「状态码必须精确匹配」「金额字段允许 0.01 误差」「时间字段只比对日期部分」。references/sample-data.json放脱敏样例,给模型参考响应结构。这两个文件模型只在需要时读,不占常驻上下文。
4. 验证请求与成功结果:端到端跑通一次 Skill 调用
配置写完,必须验证。分三层:脚本层、模型层、Skill 触发层。
脚本层先跑通。准备一个最小用例文件cases.json:
[ { "id": "ORDER-CANCEL-001", "assert_path": "status", "expect": "cancelled", "response": {"status": "cancelled", "refund": true} } ]执行:
python scripts/run_assertions.py --input cases.json期望输出ORDER-CANCEL-001 PASS expect=cancelled actual=cancelled,退出码 0。故意把 expect 改成paid再跑一次,应输出 FAIL 且退出码 1,说明断言逻辑真的在起作用,不是摆设。
模型层验证走 TaoToken 通道,用第 2 节的 curl 或模型对话页面发一句「用一句话说明测试用例的边界值覆盖」,能正常返回文本即通。这一步确认 Key、Base URL、Model ID 三件套对齐。
Skill 触发层验证:在 Claude Code 里输入「帮我给订单取消功能生成测试用例,并跑断言校验」。观察它是否自动加载test-case-generator,是否按步骤先解析、再列场景、再调run_assertions.py。成功的结果是:输出一张 Markdown 用例表,四类场景齐全,且终端里能看到脚本执行记录。如果模型没触发 Skill,回到description检查触发词是否覆盖了你实际说的话。
实测下来,最容易翻车的是脚本路径。Skill 正文里写python scripts/run_assertions.py,是相对 Skill 目录还是相对项目根目录,不同工具行为不一致。稳妥做法是在正文里写明「在 Skill 目录下执行」,或者脚本里用os.path.dirname(__file__)拼绝对路径。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth 逐条对照
排障按「先通道、再脚本、后 Skill」的顺序,别一上来就怀疑 Skill 写错。
401 Unauthorized。九成是 Key 没生效。检查三处:环境变量是否在当前 shell 生效(echo $TAOTOKEN_API_KEY看有没有值)、配置文件里 Key 是否带多余空格、Key 是否已被删除重建。注意 Base URL 和 Key 必须来自同一套配置,混用旧 Key 必 401。
local proxy failed。这类报错通常出现在工具侧配置了本地转发但转发进程没起来,或者 Base URL 填成了本地地址。把ANTHROPIC_BASE_URL直接指向https://taotoken.net/api,不要经过任何本地中间层。如果工具里有「代理」相关开关,关掉再试。
reading choices 相关报错。多见于 OpenAI 兼容格式的响应解析,工具期望choices数组但拿到的是别的结构。检查你用的接口路径和请求体格式是否匹配工具预期,Anthropic 格式走/v1/messages,OpenAI 格式走/v1/chat/completions,别混。Model ID 写错也可能导致返回结构异常,对照文档核对。
OAuth 相关报错。Claude Code 类工具首次登录会走 OAuth 流程,如果你已经用 Key 方式配置,却仍弹 OAuth,说明工具读到了旧的登录态。清掉工具的用户配置目录里与登录相关的缓存文件,重新用 Key 配置启动。三件套(Base URL、Key、Model ID)齐全时,不需要走 OAuth。
Skill 不触发。不是报错但最常被问。检查SKILL.md文件名是否全大写、文件夹是否 kebab-case、description是否包含用户实际会说的触发词。改完description要重启工具会话,因为描述是启动时预加载的。
脚本报 ModuleNotFoundError。说明脚本用了第三方库但环境没装。把脚本改成只用标准库,或者在 Skill 正文里写明依赖安装命令,别让模型猜。
6. 把 Skill 用起来:统一 Key 下的持续迭代与入口选择
Skill 建完不是终点。在SKILL.md末尾加一个## Learnings章节,每次用出问题就记一条:哪个场景漏了、哪条断言误报、哪个字段名对不上。下次会话模型加载 Skill 时会读到这些经验,相当于你的 Skill 会自己长大。
统一 Key 的好处这时候体现出来:脚本、工具、验证请求共用一套通道,出问题只看一个地方。需要新建或轮换 Key 去 API Keys 页面 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,参数细节查接入文档 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,临时验证模型通不通用模型对话 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite ,长期跑编码和 Agent 任务规划额度看 Coding Plan https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。Claude Code 相关的接入细节在 https://taotoken.net/claude-code?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite ,Anthropic 兼容配置参考 https://taotoken.net/anthropic?utm_source=taotoken_aicg_blog_end&utm_content=anthropic&utm_campaign=rewrite 。
最后一个实操建议:先只做「用例生成」这一个 Skill,跑顺两周,再往里加 scripts 和 references。一上来就搭大而全的测试平台型 Skill,大概率卡在调试脚本上,反而放弃了。小步跑通,比一次做对更重要。