名称: gherkin-authoring 描述: Gherkin 验收标准编写。用于编写 Given/When/Then 场景、特征文件或 BDD 风格规范。提供语法参考、最佳实践和 Reqnroll 集成指导。 允许工具: 读取, 全局, 搜索, 写入, 编辑
Gherkin 编写
用于可执行规范的 Gherkin/BDD 验收标准编写。
何时使用此技能
关键词: Gherkin, Given/When/Then, BDD, 行为驱动开发, 特征文件, 场景, 验收标准, Reqnroll, Cucumber, SpecFlow, 可执行规范
在以下情况下使用此技能:
- 以 Given/When/Then 格式编写验收标准
- 为 BDD 测试创建 .feature 文件
- 将需求转换为可执行规范
- 在 .NET 项目中设置 Reqnroll 测试
- 理解 Gherkin 语法和最佳实践
快速语法参考
特征文件结构
功能: <功能名称>
<功能描述>
背景:
给定 <通用前提条件>
场景: <场景名称>
给定 <前提条件>
当 <操作>
那么 <预期结果>
场景大纲: <参数化场景>
给定 <前提条件带有 <参数>>
当 <操作带有 <参数>>
那么 <预期结果带有 <参数>>
示例:
| 参数 |
| 值1 |
| 值2 |
步骤关键词
| 关键词 | 目的 | 示例 |
|---|---|---|
Given |
设置前提条件 | 给定用户已登录 |
When |
描述操作 | 当用户点击提交 |
Then |
断言结果 | 那么表单已保存 |
And |
附加步骤(相同类型) | 并且发送了邮件 |
But |
否定条件 | 但没有显示错误 |
编写有效场景
三 A 模式
Gherkin 映射到 Arrange-Act-Assert 模式:
| Gherkin | AAA | 目的 |
|---|---|---|
| Given | Arrange | 设置测试上下文 |
| When | Act | 执行被测操作 |
| Then | Assert | 验证预期结果 |
每个场景单一行为
好 - 单一行为:
场景: 用户使用有效凭证登录
给定存在注册用户
当用户输入有效凭证
那么用户已登录
坏 - 多个行为:
场景: 用户登录和资料更新
给定存在注册用户
当用户输入有效凭证
那么用户已登录
当用户更新其资料
那么资料已保存
声明式 vs 命令式风格
声明式(首选)- 做什么,而不是怎么做:
场景: 成功结账
给定顾客有商品在购物车
当顾客完成结账
那么订单已确认
命令式(避免)- 过于详细:
场景: 成功结账
给定顾客在主页上
并且顾客点击“产品”
并且顾客点击第1项上的“添加到购物车”
并且顾客点击“购物车”图标
并且顾客点击“结账”按钮
...
背景部分
使用背景为特征中所有场景共享通用设置:
功能: 购物车
背景:
给定顾客已登录
并且产品目录可用
场景: 添加商品到购物车
当顾客添加商品到购物车
那么购物车包含1件商品
场景: 从购物车移除商品
给定购物车包含商品
当顾客移除商品
那么购物车为空
背景指南
- 保持背景简短(1-3 步)
- 仅包括真正通用的设置
- 不包括所有场景不需要的任何内容
- 如果背景变得庞大,考虑拆分特征
场景大纲
使用场景大纲进行参数化测试:
场景大纲: 验证邮箱格式
给定用户注册表单
当用户输入邮箱“<邮箱>”
那么验证结果是“<结果>”
示例:
| 邮箱 | 结果 |
| user@example.com | 有效 |
| invalid-email | 无效 |
| @missing-local.com | 无效 |
| user@ | 无效 |
何时使用场景大纲
用于:
- 用不同数据测试相同逻辑
- 边界测试
- 错误消息变体
- 多个有效/无效输入
避免当:
- 场景有根本不同的流程
- 设置在不同示例之间差异显著
- 只有1-2个示例(使用单独场景)
标签
用标签组织和过滤场景:
@smoke @authentication
功能: 用户登录
@happy-path
场景: 成功登录
...
@security @negative
场景: 多次失败尝试后账户锁定
...
常见标签类别
| 类别 | 示例 |
|---|---|
| 优先级 | @critical, @high, @medium, @low |
| 类型 | @smoke, @regression, @e2e |
| 特征 | @authentication, @checkout, @search |
| 状态 | @wip, @pending, @manual |
| 非功能性 | @security, @performance, @accessibility |
与规范规范集成
Gherkin 验收标准映射到规范规范:
需求:
- id: "REQ-001"
文本: "当用户提交有效凭证时,系统应验证用户"
优先级: 必须
耳朵类型: 事件驱动
验收标准:
- id: "AC-001"
给定: "具有有效凭证的注册用户"
当: "用户提交登录表单"
那么: "用户已验证"
并且:
- "会话已创建"
- "用户被重定向到仪表板"
映射规则
| 规范字段 | Gherkin 元素 |
|---|---|
acceptance_criteria.given |
Given 步骤 |
acceptance_criteria.when |
When 步骤 |
acceptance_criteria.then |
Then 步骤 |
acceptance_criteria.and |
附加 And/But 步骤 |
最佳实践
场景命名
好:
- 描述被测试的行为
- 使用领域语言
- 指定结果
场景: 用户注册后收到确认邮件
场景: 当数量更改时购物车总计更新
场景: 搜索返回相关结果按相关性排序
坏:
- 通用或模糊
- 实现焦点
- 缺少结果
场景: 测试注册
场景: 点击添加按钮
场景: 验证数据库
步骤可重用性
编写可重用的步骤:
可重用:
给定具有角色“<角色>”的用户
给定用户有“<数量>”件商品在购物车
当用户执行“<操作>”
不可重用:
给定 John Smith 以管理员身份登录
给定用户有3件商品在购物车用于结账测试
当用户点击蓝色提交按钮
避免耦合到 UI
好 - 行为焦点:
当用户提交带有无效数据的表单
那么显示错误消息
坏 - UI 耦合:
当用户点击底部的红色提交按钮
那么在表单下方出现红色错误 div
Reqnroll 集成 (.NET)
步骤定义示例
[Binding]
public class LoginSteps
{
private readonly ScenarioContext _context;
public LoginSteps(ScenarioContext context)
{
_context = context;
}
[Given(@"存在注册用户")]
public void GivenARegisteredUserExists()
{
var user = new User("test@example.com", "password123");
_context["user"] = user;
}
[When(@"用户输入有效凭证")]
public void WhenTheUserEntersValidCredentials()
{
var user = _context.Get<User>("user");
var result = _authService.Login(user.Email, user.Password);
_context["loginResult"] = result;
}
[Then(@"用户已登录")]
public void ThenTheUserIsLoggedIn()
{
var result = _context.Get<LoginResult>("loginResult");
result.Success.Should().BeTrue();
}
}
项目设置
<PackageReference Include="Reqnroll" Version="2.*" />
<PackageReference Include="Reqnroll.NUnit" Version="2.*" />
应避免的反模式
| 反模式 | 问题 | 修复 |
|---|---|---|
| 特征长度场景 | 难以维护 | 拆分为焦点场景 |
| 命令式步骤 | 脆弱、冗长 | 使用声明式风格 |
| 技术术语 | 业务不可读 | 使用领域语言 |
| 耦合到 UI | 在 UI 更改时中断 | 专注于行为 |
| 没有背景 | 重复的 Given 步骤 | 提取通用设置 |
| 过多示例 | 缓慢、冗余 | 仅测试边界情况 |
验证检查清单
在最终确定 Gherkin 场景前:
- [ ] 每个场景单一行为
- [ ] 声明式,非命令式
- [ ] 使用领域语言
- [ ] Given 仅建立上下文
- [ ] When 包含单一操作
- [ ] Then 断言可观察结果
- [ ] 无实现细节
- [ ] 场景名称描述行为
参考
详细文档:
相关技能:
canonical-spec-format- 规范规范结构spec-management- 规范工作流导航ears-authoring- EARS 需求模式
最后更新: 2025-12-24
版本历史
- v1.0.0 (2025-12-26): 初始发布