关于 api-testing
api-testing 是帮助编码 Agent 为 REST 和 GraphQL API 编写自动化测试的技能,适用于需要验证真实测试环境中 API 契约的团队。它涵盖响应 schema、状态码、请求头、认证边界及性能断言。
主要功能
- 01用 schema 验证响应结构
- 02覆盖状态码、请求头与认证边界
- 03测试 REST 与 GraphQL 接口
- 04使用 Playwright APIRequestContext 测试
- 05断言响应时间、负载大小与并发表现
适用场景
- 01在 CI 中发现 API 响应结构变更
- 02验证登录、权限及错误响应行为
- 03通过 API 准备数据并检查页面结果
- 04测试分页、上传下载或 Webhook 接口
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ petrkindlmann/ qa-skills --skill api-testing安装后在 Claude Code 中输入/api-testing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/playwright-setup.mdschema-validation.mdtest-patterns.md详细介绍
调研问题
先检查 .agents/qa-project-context.md;如果存在,就使用其中的信息,并跳过已回答的问题。然后:
- REST、GraphQL,还是两者都有? 仅限 REST 的测试套件使用标准 HTTP 断言。GraphQL 需要查询/变更构建器,并且适合使用内省差异快照。
- 身份验证机制是什么? JWT、API 密钥、OAuth 2.0 或会话 Cookie——每种机制都需要不同的测试夹具策略。
- 是否有 OpenAPI/Swagger 规范? 如果有,可自动生成 Zod 架构作为契约(
orval、openapi-zod-client),并考虑使用 Schemathesis 进行规范驱动的模糊测试。
核心原则
- 测试契约,而非实现。 断言响应结构、状态码和标头,而非内部逻辑或数据库状态。
- 架构验证能在偏差破坏使用方之前将其捕获。 架构测试失败意味着你在前端发现问题之前,就捕获了破坏性变更。
- 身份验证流程也要测试。 测试应用的登录、登出、过期和权限契约。仅在支持刷新时测试刷新流程。清除客户端 Cookie 并不能证明服务器撤销了会话。
- 响应时间是可测试的断言。 在 CI 中发现性能回退,比处理生产事故成本更低。
探索与自动化:工具选择
API 探索(调试、手动探测、OpenAPI 在线体验)和自动化 API 测试是不同的工作。请为每项工作选用合适的工具:
| 工具 | 最适合 | 原因 |
|---|---|---|
| Bruno (v3.4+) | 基于文件的集合、可通过 Git 审查的工作流、Postman 的 FOSS 替代品 | 以文件系统为先,无需云同步;支持 gRPC、OAuth 和 GraphQL 查询构建器 |
| Hurl (8.x) | 纯文本 HTTP 测试、CI 冒烟检查 | 一个文件即可包含多个请求和断言;任何能运行 curl 的环境都能运行;支持证书和 JSONPath(RFC 9535)查询 |
| Hoppscotch | 基于 Web 的 Postman 式探索 | 开源,可在浏览器中运行,适合快速检查 |
Playwright APIRequestContext | 在测试运行器中运行自动化测试 | 本技能的重点——详见下文 |
| Supertest (Node) / httpx (Python) | 针对自有应用的进程内 API 测试 | 当你控制两端时,可获得最快反馈 |
新项目请避免使用 Postman/Insomnia,除非团队已经在这些工具上投入了大量资源——基于文件的工具(Bruno、Hurl)更便于在 PR 中审查,而且即使集合出现偏差也能继续使用。
Playwright API 测试
APIRequestContext 支持独立 API 测试,无需启动浏览器,并与浏览器上下文共享 Cookie/存储状态。适用于:
- 独立 API 测试——使用
request.get/post/...并断言状态、标头和请求正文。 - 浏览器 + API 组合测试——通过 API 创建数据,断言数据会显示在 UI 中,然后通过 API 清理。
- 已验证身份的测试夹具——在测试夹具中登录一次,将预先完成身份验证的
APIRequestContext交给测试,并在拆卸时释放。切勿硬编码令牌。
请参阅 references/playwright-setup.md,了解 playwright.config.ts、独立测试、浏览器 + API 组合测试以及已验证身份的 API 测试夹具。
架构验证
使用架构验证响应形状,而不是通过 toHaveProperty 对单个字段进行抽查。常见方法有两种:
- Zod 4 — 定义架构,对响应执行
safeParse,并断言result.success。如果验证失败,则记录result.error.issues,以便精准定位差异。使用 Zod 4 原生字符串格式:z.email()、z.uuid()、z.iso.datetime()——链式写法z.string().email()已弃用,并计划移除。 - AJV with JSON Schema — 如果你已有 JSON Schema(例如来自 OpenAPI 规范),则使用
ajv+ajv-formats编译并验证。
**以架构作为契约:**让 API 和测试都导入同一个架构文件。如果响应形状发生变化,消费者测试会立即失败。对于 OpenAPI 规范,可自动生成架构(orval 或 openapi-zod-client)。对于规范优先的团队,可将 Schemathesis 添加为 CI 任务,针对规范对线上 API 进行模糊测试,以发现未记录的形状和边缘情况下的 500 错误。
关于 Zod 4、AJV、以架构作为契约以及 Schemathesis 的实现,请参阅 references/schema-validation.md。
测试模式
为每个端点编写一个成功路径测试,以及至少一个错误路径测试。常见模式如下:
- CRUD 生命周期 — 使用
describe.serial块依次创建、读取、更新、删除,然后验证 404。各步骤之间传递资源 ID。 - 身份验证流程 — 登录成功、凭据无效、过期、登出/撤销以及权限边界。断言文档中规定的状态码和响应体:对于外部 ID 和未知 ID,资源可以有意返回无法区分的 404。应用支持令牌刷新时,也要测试令牌刷新。
- 错误响应 — 400(格式错误的请求体)、422(包含字段详情的验证错误)、429(速率限制 +
retry-after)。不要只提供成功路径测试套件。 - 响应头 — 直接断言
content-type、cache-control和速率限制响应头(不要将断言放在可能永远不会触发的条件语句后面)。请参阅下方的模式。 - 分页 — 首页元数据、超出范围时的空页,以及对无效页面大小的拒绝。
- 文件上传/下载 — 验证 multipart 上传和
content-disposition响应头。 - GraphQL — 使用一个小型
gql辅助函数,然后测试查询、变更、无效查询(错误数组),并添加内省差异快照,以捕获被静默移除的字段。 - Webhooks — 启动一个临时 HTTP 服务,注册 webhook,触发事件,并断言已投递。
关于上述所有模式的完整可运行实现以及性能断言,请参阅 references/test-patterns.md。
响应头
响应头承载着契约信息:缓存指令、速率限制信息、内容类型、CORS 策略。使用 response.headers() 断言,并通过小写名称索引;不要将断言置于 if (rateLimited) 这样的条件语句后,因为该条件可能不会触发。
test('GET /api/users sets expected response headers', async ({ request }) => {
const response = await request.get('/api/users');
const headers = response.headers();
expect(headers).toBeDefined();
expect(headers['content-type']).toContain('application/json');
expect(headers['cache-control']).toBeDefined(); // "no-store" | "max-age=60" | ...
});
关于速率限制和 retry-after 的变体,请参阅 references/test-patterns.md(响应头验证)。
性能断言
响应时间和负载大小都可以作为测试断言——断言热点端点在预算时间内响应(例如 500ms)、负载不超过大小上限,以及 API 在突发并发请求下不会出现 5xx。代码请参阅 references/test-patterns.md(性能断言部分)。
工作流证据
HTTP 请求成功或最终状态正常,都可能掩盖中间状态转换错误。 应选择能够区分预期效果与可能故障的观察方式:
- **撤销:**注销前捕获有效会话,通过正常客户端注销, 然后从独立环境重放旧凭据。断言受保护的请求被拒绝。不要将捕获的凭据放入报告或源代码管理。
- **持久化:**在被测操作完成后立即读取或重启,避免后续写入代替该操作保存状态。重试前检查回滚,之后检查是否成功恢复。必要时使用真实的应用程序/数据库状态,并提供明确的测试支持。
- **计算值:**使用独立已知的单位值,并测试多种组合。一个正确的汇总值可能掩盖两个相互抵消的错误。测试允许范围内的边界值,也测试超出允许范围的值。
- **原始请求体签名:**对发送的确切字节进行签名。加入有效的非规范 JSON 表示形式(例如含有额外空格),并加入字节被篡改后遭拒绝的用例。验证前解析并重新序列化,不得悄然重新定义已签名的消息。
- **幂等性:**断言并发重复请求后以及重启后,业务效果都只持久化一次。检查使用相同键但负载已更改的情况。幂等状态不要求每次请求都返回相同状态码;如果这是约定,重复的 DELETE 请求可能先返回 204,随后返回 404。
评估测试质量时,对每项关键断言都保留有效对照和故意破坏的对照。将未发现对照中的问题报告为覆盖缺口,而非产品故障。
反模式
1. 硬编码认证令牌
令牌会过期、轮换,并因环境而异。使用能够动态获取令牌的登录固定装置。
2. 对生产环境进行测试
API 测试会创建、修改和删除数据。应在专用测试环境或本地实例中运行。
3. 不验证错误响应
仅测试正常路径的测试套件会遗漏拒绝行为。测试每个端点文档所述的错误路径,并断言没有发生禁止的副作用;不要要求每个端点都返回所有 HTTP 状态码。
4. 仅在特定条件下断言标头
标头包含缓存指令、速率限制信息、内容类型和 CORS 策略。应对每个相关响应直接断言这些标头——藏在 if (rateLimited) 中的检查可能永远不会运行,因而无法证明任何内容。
5. 创建测试数据后不清理
创建资源却不删除的测试会污染数据库。使用 afterEach/afterAll 钩子或固定装置清理流程。
6. 将 API 测试当作单元测试
不要模拟数据库——API 测试要从使用者的角度验证契约。只模拟你不负责维护的真正第三方服务(支付网关、外部 SaaS)。
7. 忽略幂等性
重复调用 PUT 和 DELETE 时,应保持预期状态。根据端点文档规定的响应契约检查每次尝试的响应、状态和副作用。
完成标准
- 每个目标端点至少有一个正常路径测试和一个错误路径测试(验证 4xx 或 5xx 响应)。
- 测试已支持的认证流程:成功登录、无效凭据、过期、注销/撤销以及文档规定的权限边界;若已实现刷新流程,也应包含在内。
- 使用 Zod 4 或 AJV 断言响应结构的模式验证,而不只是通过
toHaveProperty进行零散检查。 - 至少应断言
content-type以及 API 设置的任何缓存/速率限制标头,并且这些断言必须无条件执行。 - 对于任何由其他团队或服务使用的端点,都应设置契约测试(共享模式文件;如需使用消费者驱动验证,请采用
contract-testing)。 - 对真正的第三方调用(支付网关、外部 SaaS)进行模拟或虚拟化;API 和其数据库必须实际运行。
- CI 中的测试套件任务在测试环境中运行后以 0(绿色)退出。
参考文件(位于 references/)
- playwright-setup.md —
playwright.config.ts、独立 API 测试、浏览器 + API 组合测试,以及经过身份验证的APIRequestContextfixture。 - schema-validation.md — Zod 4 和 AJV/JSON-Schema 响应验证、以 schema 作为契约的模式,以及基于规范的 Schemathesis 模糊测试。
- test-patterns.md — 可运行的 CRUD 生命周期、身份验证流程、错误响应、响应标头、分页、文件上传/下载、GraphQL(+ 内省差异)、webhook 和性能测试。
相关技能
- contract-testing — 使用 Pact/broker 进行消费者驱动的契约验证;当另一支团队使用你的 API,且你需要保证兼容性而不只是共享 schema 时,请查看此处。
- playwright-automation — 基于浏览器的 E2E 测试、Page Object Model,以及浏览器 + API 组合模式。
- ci-cd-integration — 在 CI 流水线中运行 API 测试套件、并行化和环境管理。
- test-strategy — 决定在 API 层、单元测试层和 E2E 层分别测试什么。