使用Selenium Grid与JUnit5,如何从指定节点重启失败的长测试?
从特定节点重新执行长耗时Selenium测试的解决方案
针对用Selenium Grid+JUnit5运行超长时间测试(30分钟),因定位器小问题失败后需从头执行的痛点,以下是几种可行方案:
1. 拆分测试步骤+状态快照
将长测试拆分为多个独立的业务步骤,每个步骤完成后保存当前Selenium会话的关键状态(Cookie、LocalStorage、当前页面URL、已完成的业务上下文)。通过系统参数指定从某一步骤开始执行,跳过前置步骤并直接加载对应状态。
示例代码思路:
@TestTemplate void executeLongTestSteps(TestInfo testInfo) { int currentStep = extractStepNumber(testInfo.getDisplayName()); int startStep = Integer.getInteger("startFromStep", 1); if (currentStep < startStep) { return; } // 若为起始步骤,加载前置状态 if (currentStep == startStep && startStep > 1) { loadSessionState(driver, "step-" + (startStep - 1) + ".state"); } // 执行当前步骤逻辑 switch(currentStep) { case 1: // 初始化流程:登录、进入目标页面 saveSessionState(driver, "step-1.state"); break; case 2: // 执行表单填写步骤 saveSessionState(driver, "step-2.state"); break; // 后续步骤依次实现 } } // 自定义方法:保存会话状态到本地文件 private void saveSessionState(WebDriver driver, String filePath) { Map<String, Object> state = new HashMap<>(); state.put("cookies", driver.manage().getCookies()); state.put("url", driver.getCurrentUrl()); // 序列化state到文件 } // 自定义方法:从文件加载会话状态 private void loadSessionState(WebDriver driver, String filePath) { Map<String, Object> state = /* 从文件反序列化 */; driver.get((String) state.get("url")); Set<Cookie> cookies = (Set<Cookie>) state.get("cookies"); cookies.forEach(cookie -> driver.manage().addCookie(cookie)); driver.navigate().refresh(); }
2. Selenium Grid会话复用
启动Grid节点时添加--session-reuse true参数,允许测试会话在失败后保留。修复定位器后,通过已有的sessionId重新连接到Grid上的存活会话,直接从失败节点继续执行。
示例代码:
// 测试失败时,打印sessionId到控制台 System.out.println("Current session ID: " + ((RemoteWebDriver) driver).getSessionId()); // 修复后,用该sessionId重新连接 DesiredCapabilities caps = new DesiredCapabilities(); // 设置和原测试一致的capabilities RemoteWebDriver driver = new RemoteWebDriver(new URL("http://grid-host:4444/wd/hub"), caps); driver.setSessionId("your-existing-session-id"); // 直接执行失败节点的逻辑 driver.findElement(By.id("fixed-locator")).click();
3. 拆分独立测试类+标签执行
将长测试拆分为多个独立JUnit测试类,用@Order控制执行顺序,@Tag标记业务节点。失败后,直接运行对应标签的测试,同时在测试类中加载前置状态,跳过已完成的流程。
示例结构:
@Order(1) @Tag("user-login") class UserLoginTest { @Test void loginAndSaveState() { // 登录逻辑,保存状态到文件 saveSessionState(driver, "login.state"); } } @Order(2) @Tag("order-submit") class OrderSubmitTest { @BeforeEach void loadLoginState() { // 加载登录状态,跳过登录步骤 loadSessionState(driver, "login.state"); } @Test void submitOrder() { // 执行订单提交逻辑 } }
若order-submit步骤失败,修复后直接运行该标签的测试:
mvn test -Dgroups=order-submit
4. 自定义JUnit5扩展实现断点续跑
编写JUnit5扩展,实现BeforeTestExecutionCallback和AfterTestExecutionCallback接口,在每个测试方法执行前后自动保存/加载状态。通过系统参数resumeFromTest指定从某个测试方法开始执行,跳过前置方法。
内容的提问来源于stack exchange,提问作者Maria
相关产品推荐
相关产品推荐

