1. 概述

在这个教程中,我们将学习三种不同的方法来覆盖Cucumber选项值。从优先级角度看,Cucumber会解析并覆盖来自以下来源的选项:

  • 系统属性、环境变量以及cucumber.properties文件
  • @CucumberOptions注解
  • 命令行参数

为了展示每种方法,我们将运行一个包含两个场景的简单特性文件,并覆盖Cucumber的tags选项。

2. 准备工作

在介绍每种方法之前,我们需要做一些初始设置。首先,添加以下依赖项:cucumber-javacucumber-junitcucumber-spring,以及junit-vintage-engine

<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-java</artifactId>
    <version>7.14.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-junit</artifactId>
    <version>7.14.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>io.cucumber</groupId>
    <artifactId>cucumber-spring</artifactId>
    <version>7.14.0</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <version>5.10.0</version>
    <scope>test</scope>
</dependency>

接下来,实现一个带有两个端点的简单控制器:

@RestController
public class HealthCheckController {

    @GetMapping(path = "/v1/status", produces = APPLICATION_JSON_VALUE)
    public HttpStatus getV1Status() {
        return ResponseEntity.ok().build().getStatusCode();
    }

    @GetMapping(path = "/v2/status", produces = APPLICATION_JSON_VALUE)
    public HttpStatus getV2Status() {
        return ResponseEntity.ok().build().getStatusCode();
    }
}

现在我们可以添加特性文件和两个场景:

Feature: status endpoints can be verified
    @v1
    Scenario: v1 status is healthy
        When the client calls /v1/status
        Then the client receives 200 status code

    @v2
    Scenario: v2 status is healthy
        When the client calls /v2/status
        Then the client receives 200 status code

最后,添加所需的Cucumber粘合代码:

@When("^the client calls /v1/status")
public void checkV1Status() throws Throwable {
    executeGet("http://localhost:8082/v1/status");
}

@When("^the client calls /v2/status")
public void checkV2Status() throws Throwable {
    executeGet("http://localhost:8082/v2/status");
}

@Then("^the client receives (\\d+) status code$")
public void verifyStatusCode(int statusCode) throws Throwable {
    final HttpStatus currentStatusCode = latestResponse.getStatusCode();
    assertThat(currentStatusCode.value(), is(statusCode));
}

默认情况下,如果没有指定,Cucumber会运行所有场景。让我们通过运行测试来验证这个行为:

mvn test

正如预期,两个场景都被执行了:

[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0

现在我们准备好了解三种不同的方法,用于覆盖Cucumber选项值。

3. 使用cucumber.properties文件

第一种方法从系统属性、环境变量和cucumber.properties文件加载Cucumber选项。

cucumber.properties文件中添加cucumber.filter.tags属性:

cucumber.filter.tags=@v1

再次运行测试时,只会执行@v1场景:

[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

4. 使用@CucumberOptions注解

第二种方法使用@CucumberOptions注解。添加tags字段:

@CucumberOptions(tags = "@v1")

再运行一次测试,只会执行@v1场景:

[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

注意:这种方法将覆盖任何通过系统属性、环境变量或cucumber.properties文件提供的值。

5. 使用命令行参数

最后一种方法使用Cucumber CLI运行器和tags参数。确保使用正确的类路径,包括编译后的类和资源以及所有依赖项(包括带有test范围的依赖项):

java -cp ... io.cucumber.core.cli.Main --tags @v1

如预期,仅执行@v1场景:

1 Scenarios (1 passed)
2 Steps (2 passed)

注意:这种方法将覆盖通过cucumber.properties文件或@CucumberOptions注解提供的任何选项。

6. 总结

在这篇文章中,我们学习了三种覆盖Cucumber选项值的方法。

第一种方法考虑了作为系统属性、环境变量以及cucumber.properties文件中提供的选项。第二种方法考虑了作为@CucumberOptions注解字段提供的选项,并覆盖了第一种方法提供的任何选项。最后一种方法使用命令行参数,并覆盖了通过先前任何方法提供的选项。

如往常一样,完整的代码可以在GitHub上找到。