HTTP 响应重复,不代表操作就是安全的。API 幂等性测试会沿着请求检查持久化结果和它可能产生的每一种业务副作用。
为什么需要这个 Skill
客户端可能在服务端提交订单后超时。如果客户端重试,响应缓存看起来正常,系统仍可能多扣一次款、重复发出事件或再次通知用户。这个 Skill 帮助团队核对写入契约和业务副作用。
Skill 能帮助你做什么
使用 API 幂等性测试 Skill,把一次写操作拆成范围明确的场景:
- 提取文档规定的键作用范围、参数匹配规则、保留时长、并发行为和冲突响应;未写明的规则要保留为问题。
- 每次改变一个条件:重复使用键、修改参数、并发提交、超时后重试,以及跨越文档规定的过期边界。
- 将响应与持久化记录关联,例如订单 ID、支付尝试和发出的事件,再用 AIT-## 记录证据及下一步验证动作。
判断依据应是契约和可观察到的副作用,而不是响应正文看起来是否相同。Awesome QA Skills 按语言和测试阶段组织 Skill;系列总览 介绍了通用安装方式。
范围与限制
这个 Skill 可以设计场景并整理现有证据;它不会替团队决定幂等键范围或过期策略、执行请求,也不会因为发生超时就断定提交成功。没有运行记录的设计复核仍是测试方案,不是执行结果。
应检查哪些契约
| 契约范围 | 需要确认的问题 | 对照的证据 |
|---|---|---|
| 键的作用范围 | 键按操作、账号、端点或其他什么边界生效? | 请求身份、认证主体、操作记录 |
| 参数身份 | 同一个键配上不同请求体时会怎样? | 规范化请求或指纹、冲突响应、写入账本 |
| 重放窗口 | 结果保留多久?过期后如何处理? | 契约版本、键记录、边界前后的时间戳 |
| 并发行为 | 第一个请求尚在处理中时,第二个请求会看到什么? | 请求时间线、锁定或占位状态、响应和提交记录 |
| 业务副作用 | 是否产生了多个持久化效果? | 通过关联字段连接订单、扣款、消息或事件 ID |
将响应重放和副作用唯一性分开判断。如果业务账本有两条写入,那么两次响应都为 202 或正文相同并不足以证明安全。
设计场景前先审计输入
| 所需材料 | 用途 | 缺失时的处理方式 |
|---|---|---|
| 写操作和预期业务副作用 | 界定哪些结果应只发生一次 | 写明未知的副作用,不自行补造 |
| 键和参数契约 | 界定等价请求与冲突 | 同键不同参数的行为保持待确认 |
| 保留时长与并发规则 | 界定时间边界 | 不从缓存设置推断过期规则 |
| 证据来源与关联字段 | 将请求连接到已提交副作用 | 指出最小补查项,结果仍标为未评估 |
记录来源版本、环境、时间范围、纳入的操作,以及能确认契约的负责人。输入笔记中区分 known、missing、conflicting、stale、out_of_scope 和 assumptions。
案例:结算已提交,但响应丢失
这是测试设计示例,不表示端点已经运行。假设购物车 cart-1842 使用键 checkout-1842 提交后,服务端创建了订单,但客户端在收到响应前超时。
场景步骤
| 步骤 | 请求或检查 | 要回答的问题 |
|---|---|---|
| 1 | 提交结算请求,保留键、请求体和请求 ID | 契约规定这次写入会创建什么? |
| 2 | 超时后,使用可用关联字段查询订单与支付记录 | 首次提交已确认、没有记录,还是仍无法确定? |
| 3 | 先串行重放,再并发提交使用同一键的请求 | 文档规定的处理中或重放行为是否成立?业务副作用有几份? |
| 4 | 改变购物车后复用原键,再核对契约定义的冲突结果 | 参数冲突如何处理?是否产生了第二次写入? |
| 5 | 为同一业务意图提交一个新键 | 按契约它是否构成新操作?这种副作用是否符合预期? |
| 6 | 在保留时长边界前后重复检查 | 迟到的重试会怎样?契约是否明确说明? |
每一步都要对照实际提供的契约。例如,不要规定所有 API 都必须返回 409,而要记录真实契约中的冲突行为。统计已提交的业务副作用,而不是 HTTP 请求次数。
示例发现
只有填入项目实际证据后才能使用以下格式:
| 字段 | 示例 |
|---|---|
| 编号与问题 | AIT-01 —— 结算已提交后重试,是否会重复创建订单或扣款? |
| 证据状态 | 关联请求记录和业务账本前保持 UNASSESSED |
| 影响与优先级 | 写明受影响的业务副作用,按项目影响标准评估;证据不足时为 NOT_SCORED |
| 负责人 | 能确认重放及过期规则的 API 或支付契约负责人 |
| 关闭条件 | 契约判断、关联后的提交账本和可重复场景结果均可复核 |
来源、运行记录和业务状态证据齐全前,不要把示例标成缺陷或通过。
交接给下一阶段
| 交接字段 | 应包含内容 |
|---|---|
| 契约 | 有版本的键作用范围、参数规则、重放窗口和冲突行为 |
| 场景 | 精确的请求变体、时间、并发方式和环境 |
| 对账 | 用于关联的字段,以及每类持久化业务副作用的数量 |
| 发现 | AIT-##、证据状态、影响依据、负责人和关闭条件 |
| 下一步 | 缺少的查询、待确认的契约决策或可重复的运行检查 |
下一位复核者应能沿着键从请求追到结果存储和副作用账本。若记录无法关联,就指出缺失了哪一环,不要声称已经实现一次且仅一次。
相关 Skill
- API 契约测试用于明确请求与响应契约。
- 重试测试用于检查重试触发条件与边界。
- API 错误契约测试用于复核冲突与处理中响应。
容易踩的坑
- 把响应一致当成业务副作用只发生一次的证明。
- 只测串行重试,不测并发请求。
- 假设不同参数、缺失键或过期键有一个放之四海而皆准的响应。
- 统计 HTTP 尝试次数,而非已提交的订单、扣款、消息或事件。
安装与调用
安装单个 Skill,并附上真实操作契约和证据来源:
npx skills add https://github.com/naodeng/awesome-qa-skills/tree/main/skills/zh/testing-types/api-idempotency-testing -g
准备设计或证据复核请求时,遵循提示词规定的输出契约:
请使用 api-idempotency-testing Skill。
任务:评估客户端超时、服务端可能已提交订单的结算 POST
输入:[契约版本、请求样例、日志、状态查询或数据路径]
范围:[纳入或排除的操作与业务副作用]
未知项:[缺失的环境、键规则、关联字段或权限]
期望输出:[按风险排序的 AIT-## 发现、证据状态和下一步验证动作]
区分事实、假设和待确认规则。没有运行记录时不要声称已经执行。
常见问题
第一次响应丢失怎么办?
先用可用的操作 ID 或键查询业务记录,确认写入状态。超时本身既不能证明成功,也不能证明失败。
服务端必须拒绝所有“同键不同参数”的请求吗?
按实际 API 契约判断。如果契约没有定义,就记录为契约缺口并交给负责人确认,不要在测试结论中自行制定策略。
只按时间过期幂等键够吗?
只有契约明确规定迟到重试的行为,并且有证据评估剩余的重复副作用风险时才够。
参考
源 Skill 与执行契约
API 幂等性测试提示词定义了工作流程和输出契约。源目录包含入口文件与配套材料。