上个月,团队里一个做接口自动化的同事跑来找我,表情有点崩溃。
“哥,我让AI生成退款接口的测试用例,它给我写了20条。跑完之后我一看,15条假通过。”
我问他什么叫假通过。他说:“比如测‘退款金额不正确’,AI的断言是assert resp.status_code == 200。HTTP 200确实返回了,但退款金额根本不对——它压根没校验金额字段。”
我说:“你把断言规则写在哪了?”
他说:“写在对话里啊。每次都要说‘断言要校验金额和订单状态’……”
我说:“那你为什么不用Skill把这三件事拆开——数据构造、依赖模拟、结果断言,各管各的?”
他愣了一下:“还能这么拆?”
能。而且这是Agent接口测试最该学的一套设计。今天这篇文章,我把“测试数据生成Skill + Mock Skill + 断言Skill”这三件套拆开讲,看完你就能拼出一套真正能发现Bug的测试能力。
一、为什么接口测试需要“三件套”?
先说说接口测试的真实困境。
一个接口测试用例,本质上要回答三个问题:输入什么数据?依赖服务怎么响应?怎么判断结果是对的?
传统方式下,这三个问题被写死在同一个Python文件里。数据是硬编码的,Mock是随手写的return {"code": 0},断言是随手写的assert resp.status_code == 200。
结果就是:上游字段一改,数据要重新构造;依赖服务行为变了,Mock要重写;业务规则变了,断言要全改。三个问题耦合在一起,改一个牵动全身。
更隐蔽的是“假通过”——Mock返回了{"code": 0, "data": {"refund_amount": 100}},断言只检查了code == 0,没检查refund_amount是否等于预期。这个用例表面通过,实际上什么都没验证。
把这三个问题拆成三个独立的Skill,每个Skill只解决一个问题,组合起来才是一条完整的测试链路。
二、Skill ①:测试数据生成——让数据“按需生长”
为什么需要单独的Skill?
传统方式下,测试数据靠硬编码。{"user_id": 12345, "amount": 100}写死在代码里。想测边界值?手动改。想测异常数据?手动改。想批量生成100条不同状态的数据?写个循环。
测试数据生成Skill解决的是:根据字段类型和约束规则,自动生成合法、非法、边界三类数据。
SKILL.md 设计
--- name: test-data-generator description: 根据字段类型、约束规则和业务场景,生成测试数据。当用户提到“生成测试数据”“构造数据”“批量造数”时触发。 when_to_use: 需要为接口测试生成请求参数时使用。适用于正常数据、边界值、异常数据的构造。 allowed-tools: Read, Write, Bash ---正文定义三类数据的生成规则:
## 任务 根据字段定义生成测试数据,覆盖三类场景。 ## 数据分类 ### 合法数据(正常流程) - 字符串:符合长度和格式要求的随机字符串 - 整数:在合法范围内的随机值 - 枚举:从允许值列表中随机选取 ### 边界数据 - 字符串:最小长度、最大长度、刚好超长 - 整数:最小值、最大值、刚好越界 - 空值:空字符串、null、空数组 ### 异常数据 - 类型错误:期望整数传字符串 - 格式错误:手机号传10位、邮箱缺@ - 业务违规:金额为负数、状态非法 ## 输出格式 JSON数组,每条数据附带: - 数据值 - 数据类型(合法/边界/异常) - 覆盖的测试点描述配套脚本
scripts/generate_data.py根据Schema定义批量生成数据。Agent不读脚本内容,只运行它并读取输出结果。
三、Skill ②:Mock Skill——让依赖服务“按剧本演”
为什么需要单独的Skill?
退款接口依赖支付网关。正常流程下,支付网关返回“退款成功”。但如果你要测“支付网关超时”“支付网关返回失败”“支付网关返回了但格式不对”——这些场景怎么构造?
传统方式下,Mock是随手写的。mock.patch("payment.refund", return_value={"code": 0})。只Mock了成功场景,异常场景没覆盖。
Mock Skill解决的是:根据依赖接口的定义和异常模式,自动生成完整的Mock策略。
SKILL.md 设计
--- name: mock-skill description: 为接口测试生成依赖服务的Mock策略,覆盖正常返回、超时、错误码、格式异常等场景。当用户提到“Mock依赖”“模拟服务”“桩数据”时触发。 when_to_use: 测试的接口依赖外部服务时使用。适用于支付网关、消息队列、第三方API等依赖的模拟。 allowed-tools: Read, Write, Bash ---正文定义Mock的覆盖维度:
## 任务 为被测接口的每个外部依赖,生成完整的Mock策略。 ## Mock覆盖维度 1. **正常返回**:依赖服务返回成功,数据格式正确 2. **业务失败**:依赖服务返回业务错误码(如“余额不足”) 3. **超时**:依赖服务响应超时 4. **连接拒绝**:依赖服务不可用 5. **格式异常**:依赖服务返回了非JSON、字段缺失、类型错误 6. **边界值**:金额为0、金额为最大值、返回空列表 ## 输出格式 每个依赖一个Mock配置: - 依赖服务名称 - 触发条件(什么情况下用这个Mock) - 模拟返回内容 - 预期被测接口的行为配套脚本
scripts/mock_server.py启动一个本地Mock服务器,Agent根据配置动态注册接口。
四、Skill ③:断言 Skill——让结果“验得准”
为什么需要单独的Skill?
这是“假通过”的根源。AI生成的断言往往是assert resp.status_code == 200,只校验了“请求发通了”,没校验“业务做对了”。
退款接口的断言应该包括:状态码是200、业务码是0、退款金额等于预期金额、订单状态变更为“已退款”、退款流水号不为空、余额增加了对应金额。
断言Skill解决的是:根据接口的响应结构和业务规则,生成多层级的断言策略。
SKILL.md 设计
--- name: assertion-skill description: 为接口测试生成多层级断言,覆盖状态码、业务码、字段存在性、字段值、业务规则校验。当用户提到“生成断言”“校验结果”“断言太弱”时触发。 when_to_use: 编写接口测试用例时使用。适用于所有需要校验接口返回结果的场景。 allowed-tools: Read, Write, Bash ---正文定义断言的四个层级:
## 任务 为接口测试生成完整的断言策略,覆盖四个层级。 ## 断言层级 ### 第一层:协议层(必须) - HTTP状态码符合预期 - Content-Type正确 ### 第二层:业务层(必须) - 业务码等于预期值 - 业务消息符合预期 ### 第三层:数据层(必须) - 关键字段存在且不为空 - 字段类型正确 - 字段值在合法范围内 ### 第四层:业务规则层(按需) - 金额计算正确(退款金额=原订单金额) - 状态流转正确(订单状态变为“已退款”) - 关联数据一致(余额增加了对应金额) ## 输出格式 Python断言代码,使用pytest风格。 每条断言附带注释说明校验的是什么。配套脚本
scripts/assert_helper.py提供常用断言的封装函数,Agent生成断言时直接调用。
五、三件套怎么串起来?
三个Skill写好了,怎么组合成一条完整的测试链路?
在Claude Code里,按顺序调用:
第1步:/test-data-generator → 生成请求参数 第2步:/mock-skill → 生成依赖Mock策略 第3步:/assertion-skill → 生成断言 第4步:组合执行测试实测效果:一个退款接口,传统方式下写一条完整测试用例(数据+Mock+断言)需要30分钟。三件套组合后,Agent在3分钟内生成全套。
更关键的是覆盖度:传统方式下,Mock只覆盖成功场景,断言只校验状态码。三件套覆盖了6类Mock场景和4层断言,边界和异常场景全被覆盖。
六、一个真实的对比
拿退款接口做对比。
传统方式生成的用例:
def test_refund(): resp = requests.post("/api/refund", json={"order_id": 123}) assert resp.status_code == 200只测了正常流程,断言只校验状态码。
三件套组合生成的用例:
# 数据:6组参数(正常、金额为0、金额超限、订单不存在、已退款、部分退款) # Mock:6种场景(成功、余额不足、超时、连接拒绝、格式异常、空返回) # 断言:4层校验(状态码、业务码、字段存在性、金额计算) @pytest.mark.parametrize("data", test_data) @pytest.mark.parametrize("mock_scenario", mock_scenarios) def test_refund(data, mock_scenario): with mock_dependency(mock_scenario): resp = requests.post("/api/refund", json=data) # 第一层:协议层 assert resp.status_code == expected_status # 第二层:业务层 assert resp.json()["code"] == expected_code # 第三层:数据层 assert"refund_id"in resp.json()["data"] # 第四层:业务规则层 assert resp.json()["data"]["refund_amount"] == data["amount"]36种组合场景,传统方式下要写两天,三件套组合后半小时生成。
七、避坑指南
坑一:Skill粒度拆得太细。三件套(数据、Mock、断言)是接口测试的最小完整单元。再往下拆(比如把断言拆成状态码断言、字段断言),AI就不知道该用哪个了。
坑二:description写得太空。“帮助生成测试数据”——等于没写。要写清楚触发条件:用户说“生成测试数据”“构造数据”“批量造数”时触发。
坑三:SKILL.md超过500行。详细的字段类型映射、Mock配置模板放到references/目录,SKILL.md只留核心流程。
坑四:让Agent“猜”业务规则。断言Skill的第四层(业务规则层)需要显式提供规则。不要指望Agent知道“退款金额=原订单金额”,要在SKILL.md里写清楚:如果需要业务规则校验,先从业务规则库读取规则,再生成断言。
坑五:忽略三个Skill的协同。数据生成Skill的输出,应该作为Mock Skill和断言Skill的输入。数据里包含“金额为0”的场景,Mock和断言要对应这个场景。三个Skill不是独立的,是一串的。
最后
Agent接口测试的核心,不是“让AI写脚本”,是“把测试逻辑拆成可复用的能力单元”。
测试数据生成Skill解决“输入什么”,Mock Skill解决“依赖怎么响应”,断言Skill解决“怎么判断对错”。三个Skill各管一段,组合起来就是一条完整的测试链路。
以前你把这三件事写在一个Python文件里,改一个牵动全身。现在你把它们拆成三个Skill,每个都能独立复用、独立迭代。
你不需要再手写第N版测试用例了。你只需要把三件套拼起来,让Agent照着跑。
下次你面对一个接口测试任务的时候,别打开编辑器了。先花30分钟把三件套搭好。
30分钟的投入,换的是未来每一个接口的测试效率。