规格里的 Given/When/Then 模板
Given/When/Then 是一种强制精确性的格式。与其写"用户可以重置密码",不如写:Given 用户有一个活跃账户,When 用户请求密码重置,Then 一个 token 发送到注册邮箱,有效期 24 小时。模糊的需求变成了可测试的——遗漏变得不可能被忽视。
快速结论
Given 负责前置条件,When 负责触发动作,Then 负责系统结果。每一段都应该具体到可验证,而不是靠会议补充解释。
你应该先看什么
- Given 写环境、角色、数据前提。
- When 写单一触发动作,不要混多个步骤。
- Then 写系统状态、返回结果和审计信号。
可直接复用的示例
- Given 订单状态为 pending - When 支付成功回调到达 - Then 订单状态更新为 paid 并写入支付流水
扩展场景模式
基础的邮箱更新示例适用于单角色、同步的交互。真实系统还需要处理异步结果、多角色流程和后台任务行为。结构不变——Given 设置前提,When 触发动作,Then 断言可观测结果——但"可观测"的范围需要扩展。
# 场景:订单完成后的异步通知 - Given 订单状态为 pending_fulfillment - When 履约服务将订单标记为已发货 - Then 向 customer.notifications 主题发布通知事件 And notification_log 写入含 orderId 和时间戳的记录 # 场景:多角色——管理员解除用户封禁 - Given 用户账号因连续 5 次登录失败被锁定 - When 管理员提交含有效理由的解锁请求 - Then user.status 变更为 active And 审计日志记录管理员 ID、理由和时间戳 # 场景:后台任务幂等性 - Given 计划中的发票任务以 jobId = job-999 运行 - When 相同 jobId 再次触发任务 - Then 不产生重复发票 And 第二次运行提前退出并记录跳过事件
异步场景应描述可观测的产物——发布的事件、数据库记录、日志条目——而非产生该结果的内部机制。如果 Then 子句需要了解实现细节才能验证,则需重写为系统层面的可观测结果。
何时拆分或合并场景
最常见的结构错误是将多个行为分支写进一个场景。规则是:每个场景只测试一个行为分支。一个同时测试成功路径和验证错误的 Given/When/Then 块无法被转换为单个测试用例——测试要么漏掉某条路径,要么依赖隐藏假设。
- 需要拆分:Then 子句包含两个独立的可验证断言,任意一个都可能单独失败。
- 需要拆分:场景标题需要用"并且"来描述测试内容。
- 可以合并:两个场景共享完全相同的 Given 状态,仅在等价的有效输入上有差异(产生相同响应)。
- 必须分开:权限路径分叉时——只读、编辑、管理员角色几乎总是需要独立场景。
评审时的快速判断:如果一个场景无法用测试框架中的单个声明式测试名称来表述,说明它范围太宽。先重命名——如果名称需要连词,就拆开场景。
将场景映射到自动化测试
场景只有链接到测试时才算完整。链接不必是测试 ID——可以是文件路径、测试函数名或 Gherkin feature 文件位置。重要的是在实现开始前建立可追溯性,而非事后补充。
- Given 映射到 fixture 设置和数据库种子状态。
- When 映射到测试触发的请求、事件或系统动作。
- Then 映射到断言:HTTP 状态码、响应体字段、数据库状态、发出的事件。
- 每个场景至少有一个能独立失败、不依赖其他场景的测试。
如果测试基础设施无法表达 Given 状态——因为 fixture 系统不支持所需的前置条件——这是扩展 harness 的信号,而非弱化场景的理由。为适应测试框架而简化的场景会成为不可靠的规格。
评审时如何发现伪 Given/When/Then
很多场景看起来符合格式,实际仍然模糊。常见信号包括:Given 写的是用户意图而不是前置状态,When 同时包含多个动作,Then 使用“正常”“成功”“合理”等无法断言的词,或者整个场景只能靠作者口头解释才能理解。
评审时可以让 QA 当场复述测试步骤。如果 QA 需要追问数据准备、权限、错误码、异步等待时间或断言位置,就说明场景还没有达到可测试状态,应先补清楚再进入实现。
好的场景不一定更长,但一定更少依赖上下文记忆。
这也是 Given/When/Then 的核心价值:把隐性假设变成团队可以逐条检查的句子。
如果团队不能逐条检查,就先不要进入自动化。
落地建议
找当前冲刺里一个模糊的需求,把它改写成三条 Given/When/Then,然后拿给开发和QA各自理解一遍。如果两分钟内产生分歧,说明这份模板在减少隐性假设上正在起作用。
相关文章
让 Given/When/Then 真正可执行
写完场景后,可以让 QA 或另一名工程师只看 Given/When/Then,不看原始需求,尝试说出需要准备什么数据、执行什么动作、用什么证据判断通过。如果对方必须追问背景,说明场景还没有达到可执行标准。
不要把多个行为塞进一个 Then。一个场景最好只保护一个关键结果,其他结果拆成独立场景。这样失败时团队能快速知道是权限、状态、数据还是界面反馈出了问题。
场景库如何维护
团队可以把常见 Given/When/Then 场景沉淀成小型场景库,例如登录权限、重复提交、空结果、超时重试、并发修改和权限降级。每次新增功能时先复用已有场景,再补充这个业务特有的状态变化。
场景库需要定期删掉过时规则。如果产品流程、权限模型或错误处理已经改变,旧场景继续留在模板里会误导 AI 编码、测试设计和人工评审。
编辑说明
本指南涵盖 规格里的 Given/When/Then 模板,面向 Spec-First 工程团队。示例为说明性场景,非生产代码。
- 作者详情: Daniel Marsh
- 编辑政策: 我们如何审核和更新文章
- 纠正: 联系编辑