1. 概述

本文将介绍 Serenity BDD——一款优秀的 行为驱动开发 (BDD) 工具。它不仅能实现自动化验收测试,还能生成图文并茂的测试报告,是开发团队的得力助手。

2. 核心概念

Serenity 的设计理念源于 BDD 思想。若想深入了解 BDD,可参考我们关于 CucumberJBehave 的文章。

2.1 需求层级

Serenity 将需求分为三级:

  1. 能力层 (Capabilities)
    如电商项目中的订单管理、会员管理等核心能力
  2. 功能层 (Features)
    每个能力包含多个具体功能
  3. 用户故事 (Stories)
    用用户故事详细描述功能细节

2.2 步骤与测试

  • **步骤 (Steps)**:封装资源操作,包含三类操作:

    • ✅ 动作操作(如点击按钮)
    • ✅ 验证操作(如断言结果)
    • ✅ 上下文操作(如设置前置条件)
    • 支持 Given-When-Then 经典格式
  • **测试 (Tests)**:每个测试描述一个用户故事,通过组合步骤实现

2.3 报告系统

Serenity 不仅记录测试结果,更能生成:

  • ✅ 需求文档
  • ✅ 应用行为说明
  • ✅ 实时更新的活文档

3. Serenity BDD 测试实战

使用 JUnit 运行 Serenity 测试时,需通过 @RunWith(SerenityRunner.class) 指定测试运行器。SerenityRunner 会自动处理步骤库并生成报告。

3.1 Maven 依赖配置

pom.xml 中添加核心依赖:

<dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-core</artifactId>
    <version>1.9.0</version>
</dependency>
<dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-junit</artifactId>
    <version>1.9.0</version>
</dependency>

添加报告聚合插件:

<plugin>
    <groupId>net.serenity-bdd.maven.plugins</groupId>
    <artifactId>serenity-maven-plugin</artifactId>
    <version>4.0.18</version>
    <executions>
        <execution>
            <id>serenity-reports</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>aggregate</goal>
            </goals>
        </execution>
    </executions>
</plugin>

⚠️ 踩坑提示:测试失败时仍需生成报告,需添加:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.20</version>
    <configuration>
        <testFailureIgnore>true</testFailureIgnore>
    </configuration>
</plugin>

3.2 会员积分系统实战

以电商会员积分功能为例:

  • 用户加入会员计划
  • 购物增加积分
  • 积分提升会员等级

测试用例实现

@RunWith(SerenityRunner.class)
public class MemberStatusIntegrationTest {

    @Steps 
    private MemberStatusSteps memberSteps;

    @Test
    public void membersShouldStartWithBronzeStatus() {
        memberSteps.aClientJoinsTheMemberProgram();
        memberSteps.theMemberShouldHaveAStatusOf(Bronze);
    }
}

步骤实现

public class MemberStatusSteps {

    private Member member;

    @Step("Given a member has {0} points")
    public void aMemberHasPointsOf(int points) {
        member = Member.withInitialPoints(points);
    }

    @Step("Then the member grade should be {0}")
    public void theMemberShouldHaveAStatusOf(MemberGrade grade) {
        assertThat(member.getGrade(), equalTo(grade));
    }
}

执行 mvn clean verify 后,报告生成在 target/site/serenity/index.html

serenity report member

点击测试用例可查看步骤详情:

serenity report member steps

待实现步骤处理

使用 @Pending 标记未完成步骤:

@Pending
@Step("When the member exchange {}")
public void aMemberExchangeA(Commodity commodity){
    //TODO
}

报告会清晰展示待办事项和失败步骤:

serenity report member steps fails pending

serenity report member fails pending tests

4. JBehave 集成

Serenity 可无缝集成 JBehave 等现有 BDD 框架。

4.1 Maven 依赖

添加 serenity-jbehave 依赖:

<dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-jbehave</artifactId>
    <version>1.9.0</version>
</dependency>

4.2 GitHub API 测试实战

延续 JBehave REST API 测试 案例:

故事描述

Scenario: Github user's profile should have a login payload same as username
 
Given github user profile api
When I look for eugenp via the api
Then github's response contains a 'login' payload same as eugenp

步骤实现

public class GithubRestUserAPISteps {

    private String api;
    private GitHubUser resource;

    @Step("Given the github REST API for user profile")
    public void withUserProfileAPIEndpoint() {
        api = "https://api.github.com/users/%s";
    }

    @Step("When looking for {0} via the api")
    public void getProfileOfUser(String username) throws IOException {
        HttpResponse httpResponse = getGithubUserProfile(api, username);
        resource = retrieveResourceFromResponse(httpResponse, GitHubUser.class);
    }

    @Step("Then there should be a login field with value {0} in payload of user {0}")
    public void profilePayloadShouldContainLoginValue(String username) {
        assertThat(username, Matchers.is(resource.getLogin()));
    }
}

步骤定义

public class GithubUserProfilePayloadStepDefinitions {

    @Steps
    GithubRestUserAPISteps userAPISteps;

    @Given("github user profile api")
    public void givenGithubUserProfileApi() {
        userAPISteps.withUserProfileAPIEndpoint();
    }

    @When("looking for $user via the api")
    public void whenLookingForProfileOf(String user) throws IOException {
        userAPISteps.getProfileOfUser(user);
    }

    @Then("github's response contains a 'login' payload same as $user")
    public void thenGithubsResponseContainsAloginPayloadSameAs(String user) {
        userAPISteps.profilePayloadShouldContainLoginValue(user);
    }
}

测试运行

使用 SerenityStory 运行测试:

import net.serenitybdd.jbehave.SerenityStory;

public class GithubUserProfilePayload extends SerenityStory {}

生成的报告比纯文本更直观:

serenity report jbehave api

5. REST-assured 集成

Serenity 支持 REST-assured 集成(参考 REST-assured 指南)。

5.1 Maven 依赖

添加 serenity-rest-assured

<dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-rest-assured</artifactId>
    <version>1.9.0</version>
</dependency>

5.2 GitHub API 测试改造

用 REST-assured 替换原有实现:

import static net.serenitybdd.rest.SerenityRest.rest;
import static net.serenitybdd.rest.SerenityRest.then;

public class GithubRestAssuredUserAPISteps {

    private String api;

    @Step("Given the github REST API for user profile")
    public void withUserProfileAPIEndpoint() {
        api = "https://api.github.com/users/{username}";
    }

    @Step("When looking for {0} via the api")
    public void getProfileOfUser(String username) throws IOException {
        rest().get(api, username);
    }

    @Step("Then there should be a login field with value {0} in payload of user {0}")
    public void profilePayloadShouldContainLoginValue(String username) {
        then().body("login", Matchers.equalTo(username));
    }
}

更新步骤定义:

public class GithubUserProfilePayloadStepDefinitions {

    @Steps
    GithubRestAssuredUserAPISteps userAPISteps;

    //...
}

报告会显示实际调用的 API,点击 "REST Query" 查看请求/响应详情:

serenity report jbehave api rest assured

6. JIRA 集成

Serenity 支持与 JIRA 无缝集成,实现需求追踪。

6.1 Maven 依赖

添加 serenity-jira-requirements-provider

<dependency>
    <groupId>net.serenity-bdd</groupId>
    <artifactId>serenity-jira-requirements-provider</artifactId>
    <version>1.9.0</version>
</dependency>

6.2 单向集成

故事中添加 JIRA 链接

Meta:
@issue #BDDTEST-1

配置 JIRA 连接

在项目根目录创建 serenity.properties

jira.url=https://your-jira-instance.com
jira.project=PROJ
jira.username=admin@example.com
jira.password=securePassword123

报告将自动包含 JIRA 链接:

serenity report jira

💡 提示:Serenity 还支持双向集成,详见官方文档

7. 总结

本文介绍了 Serenity BDD 的核心功能及其与主流测试框架的集成:

  • ✅ JUnit 基础测试
  • ✅ JBehave 故事驱动
  • ✅ REST-assured API 测试
  • ✅ JIRA 需求追踪

Serenity 的强大远不止于此,下篇将探讨如何结合 WebDriver 实现网页自动化测试。完整代码请参考 GitHub 项目


原始标题:Introduction to Serenity BDD | Baeldung