
1. 从手动点点点到Skill 编排我为什么开始攒这套工具箱做测试这行十来年前几年我最大的感受就是重复劳动把人磨平了。一个版本迭代回归用例几百条接口、UI、数据校验轮着来人就像流水线上的机械臂。后来 Agent 概念火起来我一开始是抗拒的——觉得又是概念炒作。直到我真的把几个测试环节拆成 Skill 交给 Agent 去跑才发现效率提升不是线性的是台阶式的。所谓AI 测试 Skill说白了就是把一类测试任务封装成一个可被 Agent 调用的能力单元输入是什么、输出是什么、中间调用哪些工具、失败怎么重试全部固化下来。它和传统自动化脚本最大的区别在于——脚本是死的路径写死Skill 是活的Agent 会根据上下文决定调哪个 Skill、传什么参数、拿到结果后下一步干什么。这也是为什么最近Agent、Skill、自动化测试这几个词被反复提及本质上是测试工作从写脚本往编排能力迁移。我日常在用的这 25 个 Skill覆盖了接口测试、UI 测试、数据构造、缺陷分析、报告生成、环境巡检这几大类。它们不是那种演示级的玩具而是我真实项目里每天都会触发的。有的很简单比如一个根据 Swagger 生成 pytest 用例骨架的 Skill有的比较复杂比如UI 元素定位失败后自动截图 分析 DOM 差异 给出候选定位的 Skill。这篇文章我会把这 25 个拆开讲清楚每个 Skill 解决什么问题、核心逻辑怎么设计、踩过哪些坑、怎么和 Agent 框架对接。如果你正在做AI 测试开发或者想把现有的pytest、appium、maestro这些框架和 Agent 结合起来这篇内容应该能直接抄作业。如果你只是刚听说 Skill 这个词也没关系我会从最基础的设计思路讲起保证你能看懂每个 Skill 到底在干什么。先说一个我踩过的大坑不要把 Skill 设计成万能函数。我一开始图省事写了一个执行测试的 Skill参数一大堆结果 Agent 根本不知道该传什么调用十次错八次。后来我改成一个 Skill 只干一件事比如解析接口文档、生成用例、执行单条用例、断言响应分开Agent 的调用准确率立刻上来了。这个原则后面每个 Skill 我都会体现。2. 接口测试类 Skill从文档解析到断言闭环接口测试是我用得最多的一类因为它的输入输出最结构化最适合交给 Agent 编排。这一类我一共攒了 8 个 Skill下面挑核心的讲。2.1 Swagger/OpenAPI 解析 Skill把文档变成结构化数据这个 Skill 是整个接口测试链路的起点。输入是一个 Swagger JSON 或者 OpenAPI YAML 的地址输出是一份结构化的接口清单路径、方法、请求参数、参数类型、是否必填、响应结构、状态码。核心逻辑其实不复杂但有几个细节必须处理好。第一是$ref 引用解析很多文档里 schema 是复用的直接读会拿到一个$ref字符串而不是真实结构必须递归展开。第二是allOf/oneOf/anyOf 的处理这几个组合关键字如果不处理生成的用例会漏参数。第三是example 和 schema 的优先级有 example 就用 example没有才根据 schema 造数据。我用的实现思路是 Python prance库做解析然后自己写一层递归展开。这里有个经验展开深度要设上限我设的是 10 层因为遇到过循环引用导致栈溢出的情况。展开完输出成 JSON存到一个约定的目录后面的 Skill 都从这里读。import json from prance import ResolvingParser def parse_openapi(spec_path, max_depth10): parser ResolvingParser(spec_path, recursion_limitmax_depth) spec parser.specification endpoints [] for path, methods in spec.get(paths, {}).items(): for method, detail in methods.items(): endpoints.append({ path: path, method: method.upper(), params: detail.get(parameters, []), requestBody: detail.get(requestBody, {}), responses: detail.get(responses, {}) }) return endpoints注意recursion_limit这个参数不是所有版本都支持如果你的 prance 版本较老需要自己在递归函数里加深度计数。2.2 用例骨架生成 Skill让 Agent 决定测哪些场景拿到接口清单后不是每个接口都要写全量用例。这个 Skill 的职责是根据接口的重要程度、参数复杂度、历史缺陷率生成用例骨架。骨架里包含用例名、请求方法、路径、参数模板、预期状态码但不包含具体断言逻辑——断言交给后面的 Skill。为什么这么拆因为生成什么用例和怎么断言是两个不同的决策。前者依赖业务理解后者依赖技术规则。混在一起Agent 很难判断该在哪一步介入。我在这里加了一个优先级打分逻辑参数数量超过 5 个、有枚举类型、有必填字段、历史上有过缺陷的接口优先级自动上调。这个打分表是我根据项目实际情况调的你可以根据自己的业务改。打分维度权重说明参数数量2每多一个参数加 2 分含枚举参数3枚举意味着边界场景多含必填字段2必填字段缺失是高频缺陷历史缺陷数5每出现一次缺陷加 5 分调用频率1高频接口优先覆盖2.3 数据构造 Skill边界值和异常值自动生成接口测试最烦的就是造数据。这个 Skill 输入是参数 schema输出是一组测试数据正常值、边界值、异常值。比如一个age字段类型是 integer范围 1-120它会生成1、120、0、121、-1、abc、null这几组。核心逻辑是按类型分派生成策略。字符串要考虑长度边界、特殊字符、SQL 注入片段数字要考虑最大最小、零、负数、浮点数组要考虑空数组、单元素、超长数组。这里我踩过一个坑不要生成真实可执行的注入语句只生成无害的边界字符比如和避免在测试环境造成意外。2.4 断言生成 Skill从响应 schema 反推校验点这个 Skill 输入是接口的响应 schema 和实际响应输出是一组断言。基础断言包括状态码、响应时间、字段存在性、字段类型进阶断言包括字段值范围、枚举合法性、数组长度、嵌套结构完整性。我的做法是分层断言第一层校验结构和类型第二层校验业务规则第三层校验数据一致性。Agent 在编排时如果第一层就失败了直接返回不用跑后面两层节省时间。2.5 接口执行 Skill带重试和超时控制这个 Skill 就是发请求但有几个细节必须处理。第一是超时我设的是连接 5 秒、读取 15 秒超过就判定失败。第二是重试只对网络类错误重试业务错误不重试重试次数 2 次间隔指数退避。第三是请求日志把完整的请求和响应存下来方便后面分析。import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry def build_session(): session requests.Session() retry Retry( total2, backoff_factor0.5, status_forcelist[502, 503, 504], allowed_methods[GET, POST, PUT, DELETE] ) session.mount(http://, HTTPAdapter(max_retriesretry)) session.mount(https://, HTTPAdapter(max_retriesretry)) return session提示status_forcelist里不要放 500因为 500 往往是业务逻辑问题重试没意义反而掩盖真实缺陷。2.6 依赖 Mock Skill解决上下游未就绪联调阶段最尴尬的就是上游没准备好。这个 Skill 输入是依赖接口的定义输出是一个本地 Mock 服务。我用的是responses库做进程内 Mock或者起一个轻量的 HTTP 服务做进程外 Mock。关键点是Mock 数据要可配置不能写死否则换个场景就得改代码。2.7 接口回归 Skill批量执行 差异对比这个 Skill 输入是一批用例输出是执行结果和与上次基线的差异。差异对比是重点哪些用例从通过变失败、哪些从失败变通过、哪些响应结构变了。我用的是 JSON diff 的思路但做了裁剪——只对比关键字段忽略时间戳、traceId 这类每次都变的字段。2.8 缺陷自动提单 Skill把失败用例转成缺陷描述失败用例不是直接提缺陷得先判断是不是真缺陷。这个 Skill 的逻辑是先看失败原因如果是环境问题、数据问题标记为待确认如果是断言失败且可复现自动生成缺陷描述包含用例名、请求、响应、预期、实际、复现步骤。生成的描述我要求必须包含最小复现请求方便开发直接拿去调试。3. UI 测试类 Skill定位、截图、自愈三板斧UI 测试比接口测试脆弱得多元素一变就挂。所以这一类 Skill 的设计核心是容错和自愈。我一共攒了 6 个。3.1 元素定位 Skill多策略降级单一选择器太脆弱我的做法是给每个元素配一组定位策略按优先级降级id accessibility id 文本 xpath。Agent 调用时如果第一个策略找不到自动尝试下一个全部失败才报错。这里有个经验xpath 放最后因为它最慢也最不稳定。能用 id 或 accessibility id 就别用 xpath。在 appium 里accessibility id 的稳定性通常比 xpath 高一个数量级。3.2 截图对比 Skill像素级 结构级双校验纯像素对比误报太高字体渲染、抗锯齿都会导致差异。我的做法是双校验先做像素对比如果差异超过阈值再做结构对比DOM 树或控件树对比。只有结构也变了才判定为真实 UI 变化。阈值我设的是 0.5%这个值是根据项目实际调的。太低了误报多太高了漏报多。你可以先用一批已知正常的截图跑一遍看差异分布再定阈值。3.3 自愈定位 Skill失败后自动找候选这是我最喜欢的一个 Skill。当元素定位失败时它不直接报错而是截图当前页面、分析 DOM 结构、找出与目标元素特征最相似的几个候选、返回候选列表和置信度。Agent 拿到候选后可以决定用哪个或者标记为需人工确认。实现上我用的是特征相似度文本相似度、位置相似度、层级相似度、属性相似度加权。文本权重最高因为文本通常最稳定。3.4 操作录制 Skill把手工操作转成脚本这个 Skill 输入是一段操作录屏或者操作日志输出是自动化脚本骨架。我用的是 appium 的 inspector 配合自定义的日志解析。关键点是操作去重和合并比如连续多次滑动要合并成一次带参数的滑动连续输入要合并成一次 setValue。3.5 等待策略 Skill智能等待替代硬等待sleep(5)是 UI 测试的万恶之源。这个 Skill 的职责是根据操作类型和目标元素动态决定等待策略。点击后等元素出现、输入后等值生效、跳转后等页面加载完成。我用的是显式等待 轮询超时时间根据历史执行数据动态调整。3.6 跨端适配 Skill一套用例多端执行同一个用例要在 Android、iOS、Web 上跑元素定位和操作方式都不一样。这个 Skill 的职责是做适配层用例只写业务逻辑具体的定位和操作由适配层根据当前平台翻译。这样用例维护成本大幅降低。平台定位方式操作方式等待机制Androidaccessibility id / uiautomatorappium显式等待iOSaccessibility id / predicateappium显式等待Webcss selector / xpathselenium显式等待小程序自定义专用驱动显式等待4. 数据与环境类 Skill让测试跑得起来、跑得干净测试跑不起来十有八九是数据或环境的问题。这一类我攒了 5 个 Skill。4.1 测试数据准备 Skill按用例需求造数这个 Skill 输入是用例的数据需求描述输出是准备好的数据。比如需要一个有 3 个订单的用户它会去调用户创建接口、订单创建接口把数据串起来。关键点是数据隔离每个用例用独立的数据命名空间避免互相干扰。4.2 数据清理 Skill跑完自动回收有准备就得有清理。这个 Skill 在用例执行完后触发根据准备时记录的 ID 列表反向删除数据。我要求清理必须幂等删不存在的记录不报错只记日志。4.3 环境健康检查 Skill跑测试前先体检这个 Skill 在测试开始前跑一遍检查服务是否可达、数据库是否连通、依赖的第三方服务是否正常、磁盘空间是否足够。任何一项不通过直接终止测试并告警避免跑一半挂掉浪费时间。4.4 配置注入 Skill多环境无缝切换测试环境、预发环境、生产只读环境配置都不一样。这个 Skill 的职责是根据当前环境注入正确的配置数据库地址、接口域名、账号密码。我用的是环境变量 配置文件双层覆盖环境变量优先级更高。4.5 日志采集 Skill失败现场完整保留用例失败时这个 Skill 自动采集应用日志、系统日志、网络请求日志、截图、录屏。全部打包存到一个以用例 ID 命名的目录。这样排查问题时不用到处找一个目录全搞定。5. 分析与报告类 Skill让结果能看懂、能决策测试跑完不是终点结果得能看懂、能指导决策。这一类我攒了 4 个 Skill。5.1 失败聚类 Skill把相似失败归并一次回归跑出 50 个失败可能只有 3 个根因。这个 Skill 的职责是按失败特征聚类相同错误码、相同堆栈、相同接口的失败归为一类。这样看报告时一眼就能看出主要问题在哪。5.2 根因分析 Skill从现象推原因这个 Skill 输入是失败用例的完整现场输出是可能的原因列表和置信度。比如接口返回 500 且日志里有空指针它会推断可能是某个字段未做空值判断。这个 Skill 依赖历史缺陷库做相似匹配用得越久越准。5.3 报告生成 Skill多维度可视化报告我要求包含通过率趋势、失败分布、耗时分布、缺陷密度、回归对比。用 HTML 生成可以直接在浏览器看。关键点是报告要能下钻从总览点到具体用例再点到失败现场。5.4 质量门禁 Skill卡住不达标版本这个 Skill 在 CI 流程里跑根据预设的质量门禁判断版本能不能进下一阶段。门禁规则包括通过率不低于 95%、无 P0 缺陷、核心用例全通过、性能无退化。不达标直接阻断流水线。6. 把 25 个 Skill 串起来Agent 编排的实战心得Skill 单独用价值有限串起来才是威力所在。我现在的做法是用 Agent 框架做编排每个 Skill 注册成一个可调用的工具Agent 根据任务描述决定调用顺序。6.1 编排的核心是任务分解一个跑一轮回归的任务Agent 会分解成环境检查 → 数据准备 → 接口测试 → UI 测试 → 数据清理 → 报告生成。每一步调用对应的 Skill前一步的输出作为后一步的输入。这里的关键是每个 Skill 的输入输出要标准化否则 Agent 不知道怎么传参。6.2 失败处理是编排的难点Skill 执行失败时Agent 要决定重试、跳过、还是终止。我的策略是分级处理环境类失败终止数据类失败重试断言类失败记录后继续。这个策略要写进 Agent 的提示词里否则它会乱来。6.3 并发控制不能忽视25 个 Skill 如果无脑并发数据库连接池、接口限流、浏览器实例都会爆。我的做法是按资源类型分组限流数据库类 Skill 并发不超过 5UI 类不超过 3接口类不超过 10。这个配置要根据你的实际资源调。注意Agent 编排时最容易忽略的就是并发控制我见过直接把测试环境打挂的案例。上线前一定要压测一遍。6.4 可观测性是长期维护的基础每个 Skill 的调用都要打日志谁调的、传了什么、返回什么、耗时多少。这些日志汇总起来才能分析出哪个 Skill 是瓶颈、哪个 Skill 失败率高。我用的是一套轻量的埋点每个 Skill 入口出口各打一条。7. 我踩过的坑和几条实在建议最后分享几条实打实的经验都是踩坑换来的。第一Skill 的粒度宁小勿大。我前面说过一个 Skill 只干一件事。我见过有人把登录 下单 支付做成一个 Skill结果任何一个环节变了都得改这个 Skill维护成本极高。拆成三个各自独立演进。第二Skill 的输入输出一定要有 schema。不要用随便传个字典这种方式Agent 会懵。用 JSON Schema 定义清楚每个字段的类型、是否必填、取值范围Agent 调用准确率会高很多。第三别指望 Agent 一次就对。我现在的做法是给每个 Skill 配一组示例调用Agent 在不确定时会参考示例。这比纯靠提示词描述靠谱得多。第四Skill 要能单独测试。每个 Skill 都要有独立的单元测试不能只靠端到端跑。否则出了问题你都不知道是 Skill 本身的问题还是编排的问题。第五版本管理要跟上。Skill 改了要打版本号Agent 调用时指定版本。否则今天跑通明天挂你都不知道改了什么。第六别追求一步到位。我一开始想搞一个全自动测试平台结果做了三个月发现方向错了。后来改成先攒 Skill再想编排反而跑通了。先把单个环节做扎实再考虑串联。这套东西我用了大半年最大的感受是AI 测试不是替代测试工程师而是把测试工程师从重复劳动里解放出来去做更有价值的判断。Skill 负责执行人负责设计 Skill 和判断结果。这个分工目前来看是最稳的。