1. 引言

Cucumber 是支持行为驱动开发(BDD)的测试工具。BDD 的核心优势在于让非技术人员能用自然语言描述业务功能

定义 Cucumber 测试的基石是特性(Features)、场景(Scenarios)和步骤(Steps),这些必须用 Gherkin 语言编写。本文将介绍如何在 Cucumber 的步骤间共享数据。

2. 环境准备

我们用一个处理事件的 Spring Boot 应用演示数据共享。测试将验证事件的生命周期:从进入系统的初始状态到处理后的最终状态。

先定义 Event 类:

public class Event {
    private String uuid;
    private EventStatus status;
    
    // 标准 getter/setter
}

public enum EventStatus {
    PROCESSING, ERROR, COMPLETE
}

事件处理时,状态会从初始的 PROCESSING 转为最终状态(COMPLETEERROR

现在编写初始场景和步骤定义:

Scenario: 新事件正确初始化
    When 新事件进入系统
    Then 事件正确初始化

下节将展示两个步骤如何共享事件数据。

3. 使用 Spring 共享步骤数据

@ScenarioScope 注解允许在场景的步骤间共享状态。它指示 Spring 为每个场景创建新实例,既保证步骤间数据共享,又防止场景间状态泄露

实现步骤定义前,先创建 SharedEvent 测试类存储共享数据:

@Component
@ScenarioScope
public class SharedEvent {
    private Event event;
    private Instant createdAt;
    private Instant processedAt;

    // 标准 getter/setter
}

SharedEventEvent 基础上增加了 createdAtprocessedAt 字段,便于编写更复杂的场景

最后定义场景步骤:

public class EventSteps {
    static final String UUID = "1ed80153-666c-4904-8e03-08c4a41e716a";
    static final String CREATED_AT = "2024-12-03T09:00:00Z";

    @Autowired
    private SharedEvent sharedEvent;

    @When("新事件进入系统")
    public void createNewEvent() {
        Event event = new Event();
        event.setStatus(EventStatus.PROCESSING);
        event.setUuid(UUID);
        sharedEvent.setEvent(event);
        sharedEvent.setCreatedAt(Instant.parse(CREATED_AT));
    }

    @Then("事件正确初始化")
    public void verifyEventIsInitialized() {
        Event event = sharedEvent.getEvent();
        assertThat(event.getStatus()).isEqualTo(EventStatus.PROCESSING);
        assertThat(event.getUuid()).isEqualTo(UUID);
        assertThat(sharedEvent.getCreatedAt().toString()).isEqualTo(CREATED_AT);
        assertThat(sharedEvent.getProcessedAt()).isNull();
    }
}

运行特性文件后,createNewEvent()verifyEventIsInitialized() 通过 SharedEvent 成功共享数据。

3.1. 扩展场景

再编写两个多步骤场景:

Scenario: 事件处理成功
    Given 新事件进入系统
    When 事件处理成功
    Then 事件状态为 COMPLETE
    And 事件包含 processedAt

Scenario: 系统错误导致事件处理失败
    Given 新事件进入系统
    When 事件处理失败
    Then 事件状态为 ERROR
    And 事件包含 processedAt

EventSteps 类中添加新步骤定义,展示 Gherkin 的可读性和复用性特性:

实现 When 步骤:

static final String PROCESSED_AT = "2024-12-03T10:00:00Z";

@When("事件处理 (succeeds|fails)$")
public void processEvent(String processingStatus) {
    // 处理事件逻辑...

    EventStatus eventStatus = "succeeds".equalsIgnoreCase(processingStatus) ?
      EventStatus.COMPLETE : EventStatus.ERROR;
    sharedEvent.getEvent().setStatus(eventStatus);
    sharedEvent.setProcessedAt(Instant.parse(PROCESSED_AT));
}

"事件处理 (succeeds|fails)$"正则表达式,可复用匹配"事件处理成功/失败"。结尾 $ 确保精确匹配,避免误识别多余字符

实现 Then 步骤(验证 processedAt):

@Then("事件包含 processedAt")
public void verifyProcessedAt() {
    assertThat(sharedEvent.getProcessedAt().toString()).isEqualTo(PROCESSED_AT);
}

实现 Then 步骤(验证状态):

@Then("事件状态为 {status}")
public void verifyEventStatus(EventStatus status) {
    assertThat(sharedEvent.getEvent().getStatus()).isEqualTo(status);
}

@ParameterType("PROCESSING|ERROR|COMPLETE")
public EventStatus status(String statusName) {
    return EventStatus.valueOf(statusName);
}

Cucumber 的参数类型支持将表达式转换为对象。**@ParameterType 注解的 status() 方法将字符串转为 EventStatus 枚举**。通过 {status} 占位符调用,可匹配三个步骤:

  • 事件状态为 PROCESSING
  • 事件状态为 COMPLETE
  • 事件状态为 ERROR

运行新场景时,多个步骤成功共享数据。

4. 总结

本文介绍了在 Cucumber 中共享步骤数据的方法。这种机制既支持场景内数据共享,又能隔离不同场景的数据。⚠️ 需注意:步骤间数据共享会强耦合代码,降低复用性。

完整代码见 GitHub 仓库


原始标题:How to Share Data Between Steps in Cucumber | Baeldung