在 Selenium 测试中复用同一 WebDriver 变量会导致前序浏览器实例被覆盖,最终仅最后一个实例能被 quit() 关闭,造成 Chrome、Firefox 等浏览器残留进程未退出。
在 selenium 测试中复用同一 `webdriver` 变量会导致前序浏览器实例被覆盖,最终仅最后一个实例能被 `quit()` 关闭,造成 chrome、firefox 等浏览器残留进程未退出。
当您在多个 @When 或 @And 步骤中反复对同一个 driver 字段赋值(如 driver = new FirefoxDriver() → driver = new ChromeDriver() → driver = new EdgeDriver()),实际上是在不断覆盖引用:前两个浏览器的句柄丢失,JVM 无法再访问它们,@After tearDown() 中调用的 driver.quit() 仅作用于最后创建的 Edge 实例,Firefox 和 Chrome 进程因此“悬空”并持续运行。
✅ 正确做法是:为每个浏览器维护独立的 WebDriver 实例,并在 @After 钩子中显式关闭全部实例。以下是优化后的实现方案:
public class MS848Steps {
private WebDriver firefoxDriver;
private WebDriver chromeDriver;
private WebDriver edgeDriver;
@When("Website works on Firefox")
public void website_works_on_firefox() {
firefoxDriver = new FirefoxDriver();
firefoxDriver.get("https://demowebshop.tricentis.com/");
System.out.println("Website works on Firefox!");
}
@And("Website works on Chrome")
public void website_works_on_chrome() {
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
chromeDriver = new ChromeDriver(options);
chromeDriver.get("https://demowebshop.tricentis.com/");
System.out.println("Website works on Chrome!");
}
@And("Website works on Edge")
public void website_works_on_edge() {
edgeDriver = new EdgeDriver();
edgeDriver.get("https://demowebshop.tricentis.com/");
System.out.println("Website works on Edge!");
}
@Then("Website works on every browser")
public void website_works_on_every_browser() {
System.out.println("Website works on every browser!");
}
@After
public void tearDown() {
// 按顺序安全关闭所有驱动(避免 NullPointerException)
if (firefoxDriver != null) {
firefoxDriver.quit();
System.out.println("Firefox closed.");
}
if (chromeDriver != null) {
chromeDriver.quit();
System.out.println("Chrome closed.");
}
if (edgeDriver != null) {
edgeDriver.quit();
System.out.println("Edge closed.");
}
}
}
⚠️ 注意事项:
- 不要混用 close() 和 quit():close() 仅关闭当前窗口,quit() 才终止整个浏览器会话并释放资源;
- 始终检查 null 再调用 quit(),防止 NullPointerException;
- 若测试逻辑需并发执行多浏览器(非本例的串行场景),应配合 ThreadLocal
或依赖注入容器管理生命周期; - Cucumber 的 @After 默认按类级别执行一次,确保它覆盖所有已启动的驱动——而非在每个步骤后单独 quit()(这会中断后续步骤)。
总结:Selenium 多浏览器测试的关键在于引用隔离 + 显式清理。共享字段是反模式;每个浏览器应有专属 WebDriver 引用,并在测试生命周期末尾统一、安全地销毁。









