)
接口测试做到第三轮迭代的时候很多人会盯着满屏的assert response.json()[code] 200发呆。上游字段又改了几十个用例里的断言要一个一个重写。改到一半测试同事离职了接手的人看着硬编码的魔数直挠头。更糟的是现在很多团队开始用 Claude Code 或 Copilot 生成接口用例。生成是快了但产出的东西依然是硬编码断言该脆弱的还是脆弱该爆炸的迟早会爆炸。这不是工具的问题是测试逻辑的封装粒度出了问题。今天聊一套从工程现场长出来的解法——用 Skills 把校验逻辑模块化让智能体自动组合请求与校验。目录一、接口测试的“脚本地狱”正在吃掉你的时间二、从“写断言”到“教 AI 判断正确性”三、Skills 如何让智能体学会接口测试四、实战从零搭一个自动组合请求与校验的智能体五、你缺的不是工具是技能模块化思维六、最后一个问题一、接口测试的“脚本地狱”正在吃掉你的时间打开任何一个做了两年以上的接口测试仓库你大概率会看到这样的代码def test_login_success(): resp requests.post(/api/login, json{user:admin,pass:123456}) assert resp.status_code 200 assert resp.json()[code] 0 assert resp.json()[data][token] ! 这还只是“正常登录”一个用例。再加上密码错误、账号不存在、验证码过期、字段缺失……每个用例里都嵌着一堆完全重复结构的断言。字段名一改全量重测。测试套件越写越像一本锁死版本的字典业务一迭代字典就变成废纸。更让人焦虑的是AI 代码助手来了。但它也学会了复制粘贴这种硬编码只不过复制得更快、更多。硬编码断言的本质是把测试人员的判断力锁死在脚本里每一次业务变更都需要手工开锁。效率提升的边际收益全被维护成本吃掉了。二、从“写断言”到“教 AI 判断正确性”硬编码断言为什么脆弱因为它在用“具体值”定义正确性。而正确的定义本应来自接口契约和业务规则。如果一个接口文档里写了“成功时返回状态码200code字段为0data.token为非空字符串”那么这个规则就不该被人肉翻译成三行 assert而应该直接被机器消费。这就是本质变化接口测试的核心活动正在从“编写用例脚本”转向“让智能体理解契约并自主校验”。这个转向里校验逻辑必须从一次性脚本中解耦出来变成可组合、可复用的独立单元。这些单元就是 Skills。三、Skills 如何让智能体学会接口测试一个 Skill 就是一个封装好的校验能力。比如Skill 名称能力描述HttpStatusCodeSkill校验响应状态码是否符合预期JsonPathExistsSkill校验 JSON 路径是否存在且非空JsonSchemaSkill校验响应结构是否匹配 JSON SchemaResponseTimeSkill校验响应时间是否在阈值内BusinessRuleSkill校验自定义业务规则如金额计算每个 Skill 都有标准接口接收一段校验描述输出一个可执行的校验函数。而智能体的工作流是把接口文档、测试场景和已有的 Skills 清单一起丢给大模型让它自动规划“用哪些 Skill、按什么顺序、带什么参数”来完成这次校验。流程如下核心在于智能体不直接生成断言代码而是生成一份校验计划。这个计划由 Skills 解释执行。当接口字段变化时只需要重新让智能体读取新的文档重新生成校验计划Skills 本身的代码一行不用改。四、实战从零搭一个自动组合请求与校验的智能体我们直接看代码。下面是一个最小可运行的 Skills 执行框架用 Python 实现。第一步定义 Skill 基类和两个基础 Skillfrom abc import ABC, abstractmethod import requests import jsonpath_ng class BaseSkill(ABC): abstractmethod def execute(self, response, params: dict) - tuple[bool, str]: 返回 (是否通过, 失败原因) class HttpStatusCodeSkill(BaseSkill): def execute(self, response, params): expected params.get(expected, 200) if response.status_code ! expected: returnFalse, f期望状态码 {expected}, 实际 {response.status_code} returnTrue, class JsonPathExistsSkill(BaseSkill): def execute(self, response, params): path params[path] matches jsonpath_ng.parse(path).find(response.json()) ifnot matches: returnFalse, f路径 {path} 不存在或值为空 returnTrue, 第二步构建 Skill 注册表SKILL_REGISTRY { http_status_code: HttpStatusCodeSkill(), json_path_exists: JsonPathExistsSkill(), # 更多 Skills 按需注册... }第三步智能体规划与执行引擎这里用一段提示词让大模型比如 Claude根据接口文档输出校验计划。我们只把大模型返回的 JSON 计划接进来。import json def run_test_from_plan(api_doc, plan_json): plan_json 是智能体输出的校验计划结构示例 { request: {method:POST, url:/api/login, body: {...}}, checks: [ {skill:http_status_code, params:{expected:200}}, {skill:json_path_exists, params:{path:$.data.token}} ] } plan json.loads(plan_json) # 发送请求 req plan[request] if req[method] POST: resp requests.post(fhttps://your-host{req[url]}, jsonreq.get(body, {})) else: resp requests.get(fhttps://your-host{req[url]}) # 逐个执行校验 for check in plan[checks]: skill_name check[skill] skill SKILL_REGISTRY.get(skill_name) ifnot skill: print(f[WARN] 未知 Skill: {skill_name}) continue passed, reason skill.execute(resp, check.get(params, {})) ifnot passed: print(f[FAIL] {skill_name}: {reason}) else: print(f[PASS] {skill_name}) # 模拟智能体根据 API 文档生成的计划 mock_plan { request: { method: POST, url: /api/login, body: {username:admin,password:123456} }, checks: [ {skill:http_status_code, params:{expected:200}}, {skill:json_path_exists, params:{path:$.data.token}} ] } run_test_from_plan(None, mock_plan)当你需要增加新的校验维度时只需新增一个 Skill 类注册到字典里。智能体自然就能在下次规划时选用它。不用再一个用例一个用例地改断言。五、你缺的不是工具是技能模块化思维回看上面的代码会发现一个关键设计执行器完全不关心接口是什么Skills 不关心自己被谁调用。这种解耦让测试套件的演化速度能跟上业务。从工程落地角度有三条可以直接拿走用的原则凡是重复出现三次的断言模式必须抽取为 Skill。状态码校验、字段存在性校验、类型校验这些都是通用件。让接口文档当唯一的真相源。只要智能体能读懂 OpenAPI Spec你就不需要再用人眼去对着文档写断言。校验计划是可审计的。智能体生成的 JSON 计划可以进版本管理任何人随时能看清“这次接口测试到底查了哪些东西”。这条路线走下去测试人员的工作重心会从“写校验代码”转向“定义校验技能和审查校验计划”。前者的天花板是手速后者的天花板是设计能力。六、最后一个问题你现在维护的那套接口测试如果明天上游团队把接口字段全面重构你需要改多少行断言如果答案是“几乎全部”那说明你手里的不是测试资产是负债。当智能体已经能做到自动组合 Skills 完成校验人该做的事是设计出足够健壮的技能模块让 AI 有兵可用。你的断言复用率现在有多少本文部分内容参考了霍格沃兹测试开发学社整理的相关技术资料主要涉及软件测试、自动化测试、测试开发及 AI 测试等内容侧重测试实践、工具应用与工程经验整理。