如何在Cucumber中的各个步骤之间共享数据

2025/03/15

1. 简介

Cucumber是一种支持行为驱动开发(BDD)方法的测试工具,BDD使非技术利益相关者能够使用自然的领域特定语言描述业务特性

定义Cucumber测试的构建块是功能、场景和步骤,必须用Gherkin语言编写。在本教程中,我们将学习如何在Cucumber中的步骤之间共享数据。

2. 设置

我们将使用一个处理事件的简单Spring Boot应用程序来展示如何在Cucumber步骤之间共享数据,并编写BDD测试来验证事件的生命周期,从事件进入我们系统时的初始状态到处理后的最终状态。

首先,让我们定义事件类:

public class Event {
    private String uuid;
    private EventStatus status;

    // standard getters and setters
}

public enum EventStatus {
    PROCESSING, ERROR, COMPLETE
}

当我们处理一个事件时,它会从初始的PROCESSING状态转换为最终状态,即COMPLETE或ERROR

现在,让我们编写初始场景和步骤定义:

Scenario: new event is properly initialized
    When new event enters the system
    Then event is properly initialized

在下一节中,我们将看到如何在两个步骤之间共享事件数据。

3. 使用Spring在步骤之间共享数据

@ScenarioScope注解允许我们在场景中的不同步骤之间共享状态,该注解指示Spring为每个场景创建一个新实例,使步骤定义能够在它们之间共享数据,并确保不同场景之间的状态不会泄露

在实现初始场景的步骤定义之前,我们还要实现SharedEvent测试类,它将存储步骤之间要共享的状态:

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

    // standard getters and setters
}

SharedEvent类通过引入附加字段createdAt和processedAt对Event类进行了补充,帮助我们定义更复杂的场景

最后,我们来定义一下场景中使用的步骤:

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("new event enters the system")
    public void createNewEvent() {
        Event event = new Event();
        event.setStatus(EventStatus.PROCESSING);
        event.setUuid(UUID);
        sharedEvent.setEvent(event);
        sharedEvent.setCreatedAt(Instant.parse(CREATED_AT));
    }

    @Then("event is properly initialized")
    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: event is processed successfully
    Given new event enters the system
    When event processing succeeds
    Then event has COMPLETE status
    And event has processedAt

Scenario: event is is not processed due to system error
    Given new event enters the system
    When event processing fails
    Then event has ERROR status
    And event has processedAt

我们还将新的步骤定义添加到EventSteps类中,这将展示额外的Gherkin功能,从而提高步骤的可读性和可重用性。

首先,让我们实现When步骤:

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

@When("event processing (succeeds|fails)$")
public void processEvent(String processingStatus) {
    // process event ...

    EventStatus eventStatus = "succeeds".equalsIgnoreCase(processingStatus) ? EventStatus.COMPLETE : EventStatus.ERROR;
    sharedEvent.getEvent().setStatus(eventStatus);
    sharedEvent.setProcessedAt(Instant.parse(PROCESSED_AT));
}
字符串“event processing (succeeds fails)$”是一个正则表达式,允许重复使用此步骤定义,匹配“event processing succeeds”和“event processing failed”步骤。正则表达式末尾的$字符确保步骤完全匹配,而不包含任何尾随字符

接下来,让我们实现负责检查processedAt字段的Then步骤:

@Then("event has processedAt")
public void verifyProcessedAt() {
    assertThat(sharedEvent.getProcessedAt().toString()).isEqualTo(PROCESSED_AT);
}

最后,让我们添加最后的Then步骤,验证事件状态:

@Then("event has {status} 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允许我们将方法参数从Cucumber表达式转换为对象,@ParameterType status()方法将字符串转换为EventStatus枚举值,这是使用步骤定义中的{status}占位符调用的。因此,我们的步骤定义将匹配三个步骤:

  • 事件处于“PROCESSING”状态
  • 事件处于“COMPLETE”状态
  • 事件处于“ERROR”状态

新的场景现在已经准备就绪,在运行它们时,我们注意到多个步骤成功共享数据。

4. 总结

在本教程中,我们学习了如何在Cucumber中的步骤之间共享数据。此功能允许我们在场景中的步骤之间共享数据,同时保持数据在多个场景之间隔离。值得一提的是,在步骤之间共享数据会使它们紧密耦合,从而降低它们的可重用性。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章