1. 为什么选择Serenity+Selenium做电商自动化测试
电商系统的下单流程是业务核心链路,涉及商品浏览、购物车管理、订单提交、支付对接等多个关键环节。传统手工测试在这个场景下存在明显短板:每次版本迭代都需要重复执行大量固定步骤,测试人员容易疲劳导致漏测,且难以模拟高并发场景下的系统表现。这正是自动化测试的价值所在。
Serenity BDD作为一款基于Selenium的测试框架,在电商测试领域具有独特优势。它采用行为驱动开发(BDD)模式,允许我们用接近自然语言的语法编写测试用例。比如一个下单场景可以描述为:"Given 用户已登录并选择商品 When 用户提交订单 Then 系统生成待支付订单"。这种写法让测试脚本具有更好的可读性,非技术人员也能理解测试逻辑。
Selenium WebDriver则是自动化测试的基石。最新版的Selenium 4提供了更强大的元素定位能力,特别是相对定位器(Relative Locators)功能,可以基于元素间的空间关系进行定位。这在电商页面元素频繁变动的场景下非常实用,能显著提高脚本的健壮性。
二者的组合形成了完整的技术栈:
- Selenium处理底层浏览器操作
- Serenity管理测试生命周期
- 生成可视化测试报告
- 集成CI/CD流水线
提示:电商项目通常采用Page Object模式管理页面元素,Serenity对此有深度优化。其@FindBy注解支持链式定位策略,当首选定位方式失效时会自动尝试备选方案,这对付电商页面频繁改版特别有效。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境搭建与基础配置
2.1 工具链选型建议
对于Java技术栈的团队,推荐以下组合:
- JDK 11+(LTS版本)
- Maven 3.6+(依赖管理)
- Serenity 3.6.0+
- Selenium 4.1.0+
- ChromeDriver匹配本地Chrome版本
在pom.xml中需配置关键依赖:
xml复制<dependency>
<groupId>net.serenity-bdd</groupId>
<artifactId>serenity-core</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.1.0</version>
</dependency>
2.2 浏览器驱动配置技巧
电商测试通常需要跨浏览器验证,建议在serenity.conf中配置多环境支持:
json复制"environments": {
"chrome": {
"webdriver.driver": "chrome",
"chrome.switches": "--start-maximized"
},
"firefox": {
"webdriver.driver": "firefox"
}
}
常见坑点:浏览器驱动版本必须与本地浏览器严格匹配。建议使用WebDriverManager自动管理驱动版本:
java复制WebDriverManager.chromedriver().setup();
3. 电商下单流程的测试建模
3.1 典型业务流程分解
完整的电商下单流程可拆解为以下关键节点:
- 用户登录/游客访问
- 商品搜索与筛选
- 商品详情页操作
- 购物车管理
- 订单结算页
- 支付流程
- 订单结果验证
每个节点都需要设计对应的测试场景。以购物车为例,至少要覆盖:
- 添加单品
- 批量添加
- 数量修改
- 商品删除
- 优惠券应用
- 库存校验
3.2 Page Object模式实现
Serenity强化了传统的PO模式,通过@Step注解可以实现更优雅的链式调用:
java复制public class CartPage extends PageObject {
@FindBy(css=".checkout-btn")
private WebElementFacade checkoutButton;
@Step("点击结算按钮")
public void proceedToCheckout() {
checkoutButton.click();
}
}
对于动态加载的元素,建议使用自定义等待策略:
java复制public WebElementFacade getProductElement(String sku) {
return findBy("//div[@data-sku='{0}']", sku)
.withTimeoutOf(Duration.ofSeconds(10))
.waitUntilVisible();
}
4. 核心测试场景实现
4.1 商品选择测试用例
java复制@Test
public void shouldAddProductToCart() {
givenThat(user).attemptsTo(
Navigate.toProductPage("iPhone13"),
AddToCart.fromProductPage()
);
then(user).should(
seeThat(Cart.totalItems(), equalTo(1))
);
}
4.2 订单提交验证
电商系统常见的订单号生成策略需要特别验证:
java复制@Test
public void shouldGenerateOrderNumber() {
OrderNumber orderNumber = givenThat(user).attemptsTo(
SubmitOrder.withDefaultAddress()
);
then(orderNumber).should(
matchPattern("^ORD\\d{8}-[A-Z0-9]{6}$")
);
}
4.3 支付流程模拟
对于第三方支付对接,可采用Mock服务:
java复制@MockService
public class PaymentGatewayMock {
@RequestMapping("/pay")
public ResponseEntity<String> mockPay() {
return ResponseEntity.ok("SUCCESS");
}
}
5. 测试报告与问题排查
5.1 增强型报告生成
在serenity.conf中配置详细报告:
json复制"reporting": {
"requirements.dir": "src/test/resources/features",
"step.details": "true",
"screenplay.levels": "ALL"
}
执行后会生成包含以下维度的报告:
- 测试步骤截图
- 页面加载时间线
- 网络请求日志
- 控制台错误捕获
5.2 元素定位问题排查
电商页面常见的定位问题解决方案:
- 动态ID问题:
java复制@FindBy(xpath="//button[contains(@id,'add-to-cart')]")
- iframe嵌套问题:
java复制switchTo().frame("payment-iframe");
- Shadow DOM处理:
java复制WebElement shadowHost = find(By.cssSelector(".user-info"));
WebElement shadowRoot = expandShadowRoot(shadowHost);
6. 性能优化实战技巧
6.1 并行执行配置
在maven-surefire-plugin中配置:
xml复制<configuration>
<parallel>methods</parallel>
<threadCount>4</threadCount>
</configuration>
6.2 智能等待策略
针对电商页面特点定制等待:
java复制public class EcommerceWaits {
public static WaitUntilAngularReady() {
JavascriptExecutor js = (JavascriptExecutor)getDriver();
js.executeAsyncScript("var callback = arguments[arguments.length-1];" +
"if (window.angular) { angular.element(document.body).injector().get('$browser').notifyWhenNoOutstandingRequests(callback); }" +
"else { callback(); }");
}
}
6.3 测试数据管理
使用Serenity的TestDataSource管理测试数据:
java复制@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
private String username;
private String password;
}
@TestData
public static Collection<UserInfo> testUsers() {
return Arrays.asList(
new UserInfo("vip_user", "P@ssw0rd"),
new UserInfo("normal_user", "123456")
);
}
7. 持续集成实践
7.1 Jenkins流水线配置
groovy复制stage('E2E Test') {
steps {
withMaven(maven: 'M3') {
sh 'mvn clean verify -Denvironment=chrome'
}
}
post {
always {
serenityReport()
}
}
}
7.2 失败重试机制
配置重试策略:
json复制"serenity": {
"retry": {
"count": 2,
"on": ["AssertionError", "NoSuchElementException"]
}
}
8. 移动端适配方案
电商项目通常需要兼容移动端,可通过UserAgent模拟:
java复制ChromeOptions options = new ChromeOptions();
options.addArguments("--user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X)");
对于响应式布局验证,使用视口设置:
java复制getDriver().manage().window().setSize(new Dimension(375, 812));
我在实际电商项目中发现,支付流程的测试尤其需要注意时序问题。建议在关键步骤间添加明确的等待条件,但不要使用固定的Thread.sleep()。而是应该检查特定的DOM状态,比如:
java复制waitForCondition().until(
d -> ((JavascriptExecutor)d).executeScript("return document.readyState")
.equals("complete")
);
另一个实用技巧是利用Selenium的Action类处理复杂交互。比如模拟用户滑动验证码:
java复制Actions actions = new Actions(getDriver());
actions.clickAndHold(slider)
.moveByOffset(150, 0)
.release()
.perform();
