You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Selenium自动化脚本重复执行且浏览器未正常关闭问题排查

问题分析与解决方案

看起来你遇到的核心问题是脚本重复执行、浏览器未正确关闭,结合你的代码和控制台输出,我来帮你拆解原因并给出修复方案:

核心问题根源

  1. TearDown方法未被自动触发:你的SeleniumSetup类里的tearDown()只是普通方法,没有添加JUnit/Cucumber的@After注解,导致测试结束后不会自动关闭浏览器,残留的窗口会干扰后续执行。
  2. 步骤类构造函数触发重复初始化:你在ChallengingDOMSteps的构造函数里调用prepareBrowserForSelenium(),但Cucumber运行时可能会多次实例化步骤类,加上DriverSingleton的缺失/错误实现,导致每次都重新启动浏览器。
  3. DriverSingleton单例逻辑缺失:代码里依赖DriverSingleton维护全局唯一的WebDriver,但你没提供这个类的实现,大概率是单例没有正确保存driver实例,才会出现两次启动ChromeDriver的情况。

具体修复步骤

1. 修复SeleniumSetup的TearDown钩子

给tearDown()添加@After注解,改用quit()彻底关闭浏览器,并清空单例实例:

package support;
import org.junit.After;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class SeleniumSetup {
 protected WebDriver driver;

 public SeleniumSetup() { }

 public void prepareBrowserForSelenium() {
     if(DriverSingleton.getDriver() == null) {
         setup();
     } else {
         driver = DriverSingleton.getDriver();
     }
 }

 public void setup() {
     System.setProperty("webdriver.chrome.driver", "C:\\Users\\Selenium and drivers\\chromedriver.exe");
     driver = new ChromeDriver();
     driver.get("http://the-internet.herokuapp.com/");
     driver.manage().window().maximize();
     // 将初始化好的driver存入单例
     DriverSingleton.setDriver(driver);
 }

 @After // 添加上这个注解,让Cucumber自动调用
 public void tearDown() {
     if(driver != null) {
         driver.quit(); // 用quit()代替close(),彻底终止浏览器进程
         DriverSingleton.setDriver(null); // 清空单例,避免下次复用旧实例
     }
 }
}

2. 实现正确的DriverSingleton单例类

创建这个类来维护全局唯一的WebDriver实例:

package support;
import org.openqa.selenium.WebDriver;

public class DriverSingleton {
 // 私有静态变量存储driver实例
 private static WebDriver driver;

 // 私有构造函数,防止外部实例化
 private DriverSingleton() {}

 public static WebDriver getDriver() {
     return driver;
 }

 public static void setDriver(WebDriver driverInstance) {
     driver = driverInstance;
 }
}

3. 调整步骤类的初始化逻辑

把构造函数里的初始化逻辑改成Cucumber的@Before钩子,确保每个场景只初始化一次浏览器:

package steps;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import cucumber.api.java.Before; // 导入Before钩子
import pages.ChallengingDOMPage;
import pages.DropdownPage;
import support.SeleniumSetup;

public class ChallengingDOMSteps extends SeleniumSetup{

 @Before // 每个测试场景执行前只会调用一次
 public void setupBrowser() throws Exception{
     prepareBrowserForSelenium();
 }

 @Given("^I am on the landing page$")
 public void i_am_on_the_landing_page() throws Throwable {
     new ChallengingDOMPage(driver).landingPage();
 }

 @When("^I select \"(.*?)\"$")
 public void i_select(String arg1) throws Throwable {
     new ChallengingDOMPage(driver).selectChallengingDOM();
 }

 @Then("^I will be navigated to the \"(.*?)\" page$")
 public void i_will_be_navigated_to_the_page(String arg1) throws Throwable {
     if(arg1.equalsIgnoreCase("Challenging DOM"))
         new ChallengingDOMPage(driver).verifyChallegingDOMPage();
     else if(arg1.equals("Dropdown"))
         new DropdownPage(driver).verifyDropdownHeading();
 }
}

关键注意点

  • quit() vs close():close()只会关闭当前标签页,quit()会彻底终止浏览器进程,避免后台残留大量未关闭的Chrome实例。
  • 单例清空:每次tearDown时清空DriverSingleton的实例,确保下一次测试能初始化全新的浏览器。
  • 钩子替代构造函数:Cucumber的步骤类构造函数可能被多次调用,用@Before钩子能保证浏览器初始化逻辑只执行一次。

内容的提问来源于stack exchange,提问作者awalker23

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:57:38