Cucumber最佳实践Skill cucumber-best-practices

这个技能专注于Cucumber自动化测试的最佳实践,包括场景设计原则、Gherkin编写技巧、数据管理和维护策略,帮助开发者提高测试效率和协作能力。关键词:Cucumber、软件测试、自动化测试、Gherkin、最佳实践、场景设计、测试策略、SEO。

测试 0 次安装 0 次浏览 更新于 3/25/2026

name: cucumber-best-practices user-invocable: false description: Cucumber最佳实践、模式和反模式

Cucumber最佳实践

掌握有效的Cucumber测试模式和最佳实践。

场景设计原则

1. 编写声明式场景

关注什么需要发生,而不是如何发生。

命令式(实现驱动):

场景:添加产品到购物车
  假设我导航到"http://shop.com/products"
  当我在CSS中找到元素".product[data-id='123']"
  并且我点击类为"add-to-cart"的按钮
  并且我等待AJAX请求完成
  那么元素".cart-count"应该包含"1"

声明式(业务驱动):

场景:添加产品到购物车
  假设我正在浏览产品
  当我将"无线耳机"添加到购物车时
  那么我的购物车应该包含1个商品

2. 一个场景,一个行为

每个场景应只测试一个业务规则或行为。

一个场景中包含多个行为:

场景:用户注册、登录和资料更新
  假设我注册一个新账户
  当我登录时
  并且我更新我的资料
  并且我更改我的密码
  那么一切都应该正常工作

分开的场景:

场景:注册新账户
  当我使用有效信息注册时
  那么我应该收到确认邮件

场景:使用新账户登录
  假设我已经注册了一个账户
  当我使用我的凭证登录时
  那么我应该看到我的仪表板

场景:更新资料
  假设我已登录
  当我更新我的资料信息时
  那么我的更改应该被保存

3. 保持场景独立

每个场景应设置自己的先决条件。

依赖的场景:

场景:创建订单
  当我创建订单#12345时

场景:查看订单
  当我查看订单#12345时  # 依赖上一个场景!

独立的场景:

场景:查看订单
  假设一个ID为"12345"的订单存在
  当我查看订单详情时
  那么我应该看到订单信息

4. 明智地使用背景

使用背景用于通用设置,但不要过度使用。

背景的良好使用:

功能:购物车

  背景:
    假设我以顾客身份登录

  场景:添加产品到购物车
    当我添加一个产品到购物车时
    那么我的购物车应该包含1个商品

  场景:从购物车移除产品
    假设我的购物车中有一个产品
    当我移除该产品时
    那么我的购物车应该为空

背景做太多事情:

背景:
  假设我在主页上
  并且我点击菜单
  并且我导航到产品
  并且我按类别"电子产品"筛选
  并且我按价格排序
  # 设置过多!不是所有场景都需要所有这些

功能组织

分组相关场景

功能:用户认证

  场景:成功登录
    ...

  场景:密码错误登录失败
    ...

  场景:多次失败后账户锁定
    ...

有效使用标签

@冒烟 @关键
场景:使用有效凭证登录
  ...

@慢速 @集成
场景:密码重置邮件工作流
  ...

@进行中
场景:OAuth登录
  # 进行中的工作
  ...

运行特定标签:

# 运行冒烟测试
cucumber --tags "@冒烟"

# 运行除进行中外所有
cucumber --tags "not @进行中"

# 运行冒烟和关键
cucumber --tags "@冒烟 and @关键"

# 运行冒烟或关键
cucumber --tags "@冒烟 or @关键"

编写良好的Gherkin

使用领域语言

用业务领域的语言编写,而不是技术术语。

技术语言:

场景:POST请求到/api/users
  当我向"/api/users"发送JSON负载的POST请求时
  并且响应状态为201

领域语言:

场景:注册新用户
  当我注册一个新用户账户时
  那么用户应该被成功创建

保持步骤在同一层次

不要混合高层次和低层次细节。

混合层次:

场景:购买产品
  假设我已登录
  当我添加一个产品到购物车时
  并且我点击ID为"checkout-btn"的元素  # 太详细!
  并且我输入信用卡"4111111111111111"      # 太详细!
  那么我完成购买

一致层次:

场景:购买产品
  假设我已登录
  并且我的购物车中有一个产品
  当我使用信用卡结账时
  那么我的订单应该完成
  并且我应该收到确认邮件

避免连接步骤

不要用"并且"在散文体中组合多个不同的操作。

连接步骤:

当我登录并添加产品到购物车并结账时

分开步骤:

当我登录时
并且我添加一个产品到我的购物车
并且我继续结账

场景大纲

用于真正的变化

当需要用不同数据测试相同行为时使用场景大纲。

良好使用:

场景大纲:登录验证
  当我使用"<用户名>"和"<密码>"登录时
  那么我应该看到"<消息>"

  示例:
    | 用户名 | 密码   | 消息               |
    | 有效   | 有效   | 欢迎               |
    | 无效   | 有效   | 无效用户名         |
    | 有效   | 无效   | 无效密码           |
    | 空     | 空     | 用户名必填         |

过度使用场景大纲:

# 不要将场景大纲用于不相关的测试用例
场景大纲:多个功能
  当我使用功能"<功能>"时
  那么结果是"<结果>"

  示例:
    | 功能       | 结果    |
    | 登录       | 成功   |
    | 注册       | 成功   |
    | 购物车     | 空     |  # 这些是不同的行为!

保持示例有意义

场景大纲:折扣计算
  假设一个状态为"<会员级别>"的顾客
  当他们购买总额为$<金额>的商品时
  那么他们应该收到$<折扣>的折扣

  示例:标准折扣
    | 会员级别 | 金额 | 折扣 |
    | 银牌     | 100  | 5    |
    | 金牌     | 100  | 10   |
    | 白金     | 100  | 15   |

  示例:最低购买阈值
    | 会员级别 | 金额 | 折扣 |
    | 银牌     | 49   | 0    |
    | 银牌     | 50   | 2.50 |

步骤定义模式

创建可重用步骤

// 通用的,可重用的
当('我填写{string}为{string}', async function(字段, 值) {
  await this.page.fill(`[name="${字段}"]`, 值);
});

// 在多个场景中使用:
当('我填写"邮箱"为"test@example.com"')
当('我填写"密码"为"secure123"')
当('我填写"搜索"为"产品"')

避免过度通用步骤

在可重用性和可读性之间取得平衡。

太通用:

当('我用{string}和{string}做{string}', ...)

具体且可读:

当('我用{string}和{string}登录', ...)
当('我在{string}中搜索{string}', ...)

数据管理

使用工厂创建测试数据

// support/factories.js
const faker = require('faker');

class UserFactory {
  static create(overrides = {}) {
    return {
      firstName: faker.name.firstName(),
      lastName: faker.name.lastName(),
      email: faker.internet.email(),
      password: 'Test123!',
      ...overrides
    };
  }
}

// 在步骤中使用
假设('我注册一个新用户', async function() {
  const user = UserFactory.create();
  this.currentUser = user;
  await this.api.register(user);
});

避免硬编码ID

硬编码:

假设用户"12345"存在
当我查看订单"67890"时

命名实体:

假设一个用户"john@example.com"存在
当我查看我最近的订单时

错误处理

测试正常路径和异常路径

@正常路径
场景:成功结账
  假设我的购物车中有商品
  当我完成结账流程时
  那么我的订单应该被确认

@错误处理
场景:使用过期卡结账
  假设我的购物车中有商品
  当我使用过期信用卡结账时
  那么我应该看到一个错误消息
  并且我的订单不应该被处理

@边缘情况
场景:库存不足结账
  假设我的购物车中有一个产品
  但该产品缺货
  当我尝试结账时
  那么我应该被告知库存不可用

性能

标记慢速测试

@慢速 @集成
场景:带邮件通知的完整订单工作流
  # 运行需要30秒
  ...

并行执行

确保场景可以并行运行:

// cucumber.js
module.exports = {
  default: '--parallel 4'
};

维护

定期审查

  • 移除过时场景
  • 更新场景以符合需求变化
  • 重构重复步骤
  • 保持功能组织

版本控制

features/
  authentication/
    login.feature
    registration.feature
  shopping/
    cart.feature
    checkout.feature
  admin/
    user-management.feature

常见反模式

测试实现细节:

那么数据库中应该有1条用户在用户表中的记录

业务场景中的UI特定断言:

那么我应该在右上角看到一个红色错误消息

使用Given用于动作:

假设我点击提交按钮  # 这是一个When,不是Given!

技术术语:

当我向/api/v1/users发送JSON体的POST请求时

测试金字塔

在测试策略中适当使用Cucumber:

  • 端到端Cucumber测试:关键用户旅程(20%)
  • 集成测试:API/服务交互(30%)
  • 单元测试:业务逻辑(50%)

不要试图用Cucumber测试所有东西。用于高价值的验收测试。

记住:Cucumber测试应记录行为,促进协作,并从业务角度提供系统按预期工作的信心。