Selenium测试运行时ChromeDriver多次启动致用例失败问题排查
问题根因
你遇到的Chrome重复启动、测试崩溃问题,核心是代码完全没有做WebDriver实例的复用控制,每触发一次实例创建逻辑就会拉起一个全新的Chrome进程,最终耗尽系统资源导致失败,具体错误点如下:
LauchDriver类的LauDriver()方法没有单例校验,每次被调用都会执行new ChromeDriver()创建新的浏览器进程,没有任何复用已有实例的逻辑。ContactpageObjects类的无参构造方法中,每次实例化页面对象都会主动新建LauchDriver并调用LauDriver()创建新驱动,没有设计为接收外部传入的已有WebDriver实例。- 测试类中存在大量无意义的重复实例创建逻辑:
enterSearchText方法中首先手动调用LauDriver()启动第一个Chrome打开目标网址- 随后调用
getObjects()时,方法内部newContactpageObjects会触发构造器逻辑启动第二个Chrome - 之后手动new
ContactpageObjects会启动第三个Chrome - 最后调用
getObjects().getSubmit()时会启动第四个Chrome - 仅这一个测试方法就会拉起4个独立Chrome进程,后续运行
contactHeader测试方法时还会继续创建新的浏览器实例。
- 全链路没有任何浏览器退出、资源释放的逻辑,运行结束的Chrome进程会持续驻留后台占用内存、端口资源。
修复方案
1. 重构驱动管理类,实现单例复用
将WebDriver改为全局唯一实例,仅在第一次调用时初始化,同时新增统一的资源释放方法:
import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import io.github.bonigarcia.wdm.WebDriverManager; import java.time.Duration; public class LaunchDriver { private static WebDriver driver; public static WebDriver getDriver() { if (driver == null) { WebDriverManager.chromedriver().setup(); driver = new ChromeDriver(); // 可在此处统一配置全局浏览器参数 driver.manage().window().maximize(); driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10)); } return driver; } public static void quitDriver() { if (driver != null) { driver.quit(); driver = null; } } }
2. 重构页面对象类,依赖注入驱动实例
移除页面对象构造器中自行创建驱动的逻辑,改为接收外部传入的已有WebDriver实例:
import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.PageFactory; import java.util.List; public class ContactpageObjects { private WebDriver driver; public ContactpageObjects(WebDriver driver){ this.driver = driver; PageFactory.initElements(driver, this); } @FindBy(css = ".hero") List<WebElement> header1 ; @FindBy(xpath = "//input[@class = 'search__input'][@data-highlight = 'true']") WebElement searchField; @FindBy(xpath = ".//button[@class = 'search__submit']") WebElement submit; public List<WebElement> getHeader(){ return header1; } public WebElement getSearchField(){ return searchField; } public WebElement getSubmit(){ return submit; } }
3. 重构测试类,统一管理驱动生命周期
移除测试方法中重复创建驱动、重复实例化页面对象的逻辑,通过测试生命周期注解统一初始化和销毁资源:
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import static org.junit.jupiter.api.Assertions.assertEquals; public class ContactPageTest { private WebDriver driver; private ContactpageObjects pageObj; @BeforeEach public void setUp() { // 每个用例运行前获取唯一驱动实例,初始化页面对象 driver = LaunchDriver.getDriver(); pageObj = new ContactpageObjects(driver); } @Test public void enterSearchText(){ driver.get("https://www.mywebsite.uk/speed"); for(WebElement a: pageObj.getHeader()){ String text = a.findElement(By.cssSelector(".hero__title")).getText(); assertEquals("Contact", text); System.out.println(text); } pageObj.getSearchField().sendKeys("closing"); pageObj.getSubmit().click(); } @Test public void contactHeader() { driver.get("https://www.mywebsite.uk/speed"); for(WebElement a:pageObj.getHeader()){ String text = a.findElement(By.cssSelector(".hero__title")).getText(); assertEquals("Contact", text); System.out.println(text); } } @AfterAll public static void tearDown() { // 所有用例运行完成后统一退出浏览器释放资源 LaunchDriver.quitDriver(); } }
补充说明:如果需要用例之间完全隔离(避免上一个用例的操作状态影响下一个),可以将驱动初始化和退出逻辑分别放到
@BeforeEach和@AfterEach中,保证每个用例启动全新的独立浏览器,但同一个用例运行过程中绝对不能重复创建多个WebDriver实例。
内容的提问来源于stack exchange,提问作者e-Tester
相关产品推荐
相关产品推荐

