用 Cucumber 放心:如何将请求信息放入 HTML 报告中

Rest Assured with Cucumber: How to put the request information inside the HTML report

我想在我的 HTML 报告中显示我的请求和响应的详细信息。

特征文件示例:

Feature: Rest Assured under Cucumber POC

  Scenario: Azure Login Scenario
    Given Request specifications are set with base uri "https://login.microsoftonline.com/"
    When Azure Login Request Executed
    Then Verify Status Code is 200

亚军class是:

@RunWith(Cucumber.class)

@CucumberOptions(
        features = "src/main/resources/features",
        glue = {""},
        tags = "@tests",
        plugin = {      "pretty",
                        "json:target/cucumber-reports/Cucumber.json",
                        "html:target/cucumber-reports"}//reporting plugin
)
public class CucumberRunner {}

步骤是:

@Given("Request specifications are set with base uri {string}")
public void setRequestsSpec(String baseUri){

    RequestSpecification spec = new RequestSpecBuilder()
            .setBaseUri(baseUri)
            .addFilter(new ResponseLoggingFilter())//log request and response for better debugging. You can also only log if a requests fails.
            .addFilter(new RequestLoggingFilter())
            .build();

    testContext().setRequestSpec(spec);
}

@When("^Azure Login Request Executed$")
public void azureLoginExecuted() {

    response =
    given()  //Add x-www-form-urlencoded body params:
        .formParam(GRANT_TYPE_KEY, GRANT_TYPE_VALUE)
        .formParam(AUTO_TEAM_CLIENT_ID_KEY, AUTO_TEAM_CLIENT_ID_VALUE)
        .formParam(AUTO_TEAM_CLIENT_SECRET_KEY, AUTO_TEAM_CLIENT_SECRET_VALUE)
        .formParam(RESOURCE_KEY, RESOURCE_VALUE)
    .when()
        .post(AUTO_TEAM_TENANT_ID + RESOURCE); //Send the request along with the resource

    testContext().setResponse(response);

    setAuthorizationToken();
}

@Then("Verify Status Code is {int}")
public void verifyStatusCode(int expected_repsonse_code) {
    testContext().getResponse().then().statusCode(expected_repsonse_code);
}

目前我发现了如何仅在我的 IntelliJ 控制台中显示这些详细信息:

例如:

@tests
Feature: Rest Assured under Cucumber POC

  @tests
  Scenario: Azure Login Scenario                                                            # src/main/resources/features/poc.feature:5
    Given Request specifications are set with base uri "https://login.microsoftonline.com/" # CommonStepsDefinitions.setRequestsSpec(String)
Request method: POST
Request URI:    https://login.microsoftonline.com/6ae4e000-b5d0-4f48-a766-402d46119b76/oauth2/token
Proxy:          <none>
Request params: <none>
Query params:   <none>

还有更多..

但是 HTML 报告只显示:

谢谢!

我可以给你一些细节,但可能无法完全回答你的问题。

为了向 Cucumber HTML 报告中添加数据,您可以使用:

@After
public void addDataToReport(Scenario scenario) { //scenario is provided from Cucumber
    scenario.write(string with the information about scenario);
}

它不会被格式化,我不知道如何更改报告的显示方式。每条消息都将在每个测试用例下。

你必须以某种方式将信息传递给 @After 钩子。

我希望其他人能更详细地回答。

编辑:

为了存储当前运行正在发生什么场景的信息,甚至是并行的,我们可以创建一个class来存储必要的信息,基于线程,所以它将是 Thread-safe.

让我们创建一个 class 来存储 Scenario。我们称它为 Storage

public class Storage {
    private static final HashMap<Thread, Scenario> map = new HashMap<>();

    public static void putScenario(Scenario scenario) {
        map.put(Thread.currentThread(), scenario);
    }

    public static Scenario getScenario() {
        return map.get(Thread.currentThread());
    }
}

现在,我们必须以某种方式获得 Scenario。它可以通过使用 @Before 挂钩来实现,如下所示:

public class BeforeHook {

    @Before(order = 1)
    public void getScenario(Scenario scenario) {
        Storage.putScenario(scenario);
    }
}

@Before 挂钩在每个场景之前 运行。我们获取有关 Scenario 的信息并将其放入 Storage 中,这样我们就知道什么 Scenario 在什么线程上 运行。 请记住,钩子必须可以通过 Cucumber Runner 中的 glue 参数访问!

现在,如果我们想在报告中写入额外信息:

    @Then("Data is saved to the report")
    public void data_is_saved_to_the_report() {
        System.out.println("Saving data to report");
        Storage.getScenario().write("Test data and stuff");
    }

我们只是从存储中获取当前场景并使用Scenario.write()方法将信息添加到报告中。

它在报告中看起来像这样:

您只需按以下方式设置 RequestSpecification 过滤器,即可将 RestAssured 输出记录到您的 Cucumber 场景报告中:

        ByteArrayOutputStream requestResponseBuffer = new ByteArrayOutputStream();
        PrintStream requestResponsePrintStream = new PrintStream(requestResponseBuffer , true);
        List<Filter> loggingFilters = Arrays.asList(
                 new RequestLoggingFilter(requestResponsePrintStream), 
                 new CucumberReportLoggingFilter(requestResponseBuffer, scenario),
                 new ResponseLoggingFilter(requestResponsePrintStream)
        );

        RequestSpecification requestSpecification = RestAssured.given()
                .filters(loggingFilters)
                :

其中 CucumberReportLoggingFilter class 看起来像这样:

class CucumberReportLoggingFilter implements Filter {

    ByteArrayOutputStream requestResponseBuffer;
    Scenario scenario;

    CucumberReportLoggingFilter(ByteArrayOutputStream requestResponseBuffer, Scenario scenario) {
        this.requestResponseBuffer = requestResponseBuffer;
        this.scenario = scenario;
    }

    @Override
    Response filter(FilterableRequestSpecification requestSpec,
                    FilterableResponseSpecification responseSpec, FilterContext ctx) {
        // Call the next filter(s) which logs the response to the requestResponseBuffer
        Response response = ctx.next(requestSpec, responseSpec);
        scenario.write(requestResponseBuffer.toString());
        return response;
    }
}

此解决方案将自定义 CucumberReportLoggingFilter 夹在标准 RequestLoggingFilterResponseLoggingFilter 过滤器之间。

RequestSpecification 发送 Request 时发生的过滤事件顺序是:

  1. 标准 RequestLoggingFilter filter() 方法运行并将请求详细信息漂亮地打印到 requestResponseBuffer
  2. 自定义 CucumberReportLoggingFilter filter() 方法运行并调用下一个过滤器(标准 ResponseLoggingFilter 过滤器)。
  3. 标准 ResponseLoggingFilter filter() 方法运行并漂亮地将响应详细信息打印到 requestResponseBuffer
  4. 控制返回到自定义 CucumberReportLoggingFilter filter() 方法,该方法使用 scenario.write() 方法将 requestResponseBuffer 的内容发送到 Cucumber 报告。

仅在场景失败时才写出消息

您可以将上述解决方案修改为:

  1. 删除 CucumberReportLoggingFilter.
  2. 使 requestResponseBuffer 变量 'scenario-scoped'(即每个场景只有一个缓冲区)。
  3. 让在您的 stepdefs 代码中运行的最后一个 @After 挂钩检查场景结果,如果失败,将 requestResponseBuffer 的内容写入黄瓜报告。