1. 概述
本文将介绍 Serenity BDD——一款优秀的 行为驱动开发 (BDD) 工具。它不仅能实现自动化验收测试,还能生成图文并茂的测试报告,是开发团队的得力助手。
2. 核心概念
Serenity 的设计理念源于 BDD 思想。若想深入了解 BDD,可参考我们关于 Cucumber 和 JBehave 的文章。
2.1 需求层级
Serenity 将需求分为三级:
- 能力层 (Capabilities)
如电商项目中的订单管理、会员管理等核心能力 - 功能层 (Features)
每个能力包含多个具体功能 - 用户故事 (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
:
点击测试用例可查看步骤详情:
待实现步骤处理
使用 @Pending
标记未完成步骤:
@Pending
@Step("When the member exchange {}")
public void aMemberExchangeA(Commodity commodity){
//TODO
}
报告会清晰展示待办事项和失败步骤:
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 {}
生成的报告比纯文本更直观:
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" 查看请求/响应详情:
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 还支持双向集成,详见官方文档
7. 总结
本文介绍了 Serenity BDD 的核心功能及其与主流测试框架的集成:
- ✅ JUnit 基础测试
- ✅ JBehave 故事驱动
- ✅ REST-assured API 测试
- ✅ JIRA 需求追踪
Serenity 的强大远不止于此,下篇将探讨如何结合 WebDriver 实现网页自动化测试。完整代码请参考 GitHub 项目。