TestNG与Selenium并行测试中如何正确调用driver.quit()?
问题:TestNG并行测试中仅一个浏览器窗口被关闭,其余需手动关闭
我正在使用TestNG和Selenium运行4个并行测试,测试能正常同时打开4个浏览器窗口运行,但存在测试无法结束的问题:@AfterTest代码块仅触发一次,仅一个窗口关闭,其余窗口需手动关闭。请问如何让每个测试完成后都关闭对应的driver?
我的代码
Java测试类
public class SecondNGTest { public static WebDriver driver; public static ChromeOptions chromeOptions; public static final String USERNAME = "PRIVATE"; public static final String AUTOMATE_KEY = "PRIVATE"; public static final String URL = "https://" + USERNAME + ":" + AUTOMATE_KEY + "@hub-cloud.browserstack.com/wd/hub"; public static DesiredCapabilities caps; @Test public void executSessionOne() throws MalformedURLException{ //First session of WebDriver caps = new DesiredCapabilities(); caps.setCapability("os", "Windows"); caps.setCapability("os_version", "10"); caps.setCapability("browser", "Chrome"); caps.setCapability("browser_version", "80.0 beta"); caps.setCapability("browserstack.local", "false"); caps.setCapability("browserstack.selenium_version", "3.5.2"); caps.setCapability("name", "selenium test"); driver = new RemoteWebDriver(new URL(URL), caps); chromeOptions = new ChromeOptions(); String chromeDriverPath = "resources/chromedriver.exe"; System.setProperty("webdriver.chrome.driver", chromeDriverPath); //Goto guru99 site driver.get("http://google.com/"); } @Test public void executeSessionTwo() throws MalformedURLException{ //Second session of WebDriver caps = new DesiredCapabilities(); caps.setCapability("os", "Windows"); caps.setCapability("os_version", "10"); caps.setCapability("browser", "Chrome"); caps.setCapability("browser_version", "80.0 beta"); caps.setCapability("browserstack.local", "false"); caps.setCapability("browserstack.selenium_version", "3.5.2"); caps.setCapability("name", "selenium test"); driver = new RemoteWebDriver(new URL(URL), caps); chromeOptions = new ChromeOptions(); String chromeDriverPath = "resources/chromedriver.exe"; System.setProperty("webdriver.chrome.driver", chromeDriverPath); //Goto guru99 site driver.get("http://youtube.com/"); } @Test public void executSessionThree() throws MalformedURLException{ //Third session of WebDriver caps = new DesiredCapabilities(); caps.setCapability("os", "Windows"); caps.setCapability("os_version", "10"); caps.setCapability("browser", "Chrome"); caps.setCapability("browser_version", "80.0 beta"); caps.setCapability("browserstack.local", "false"); caps.setCapability("browserstack.selenium_version", "3.5.2"); caps.setCapability("name", "selenium test"); driver = new RemoteWebDriver(new URL(URL), caps); chromeOptions = new ChromeOptions(); String chromeDriverPath = "resources/chromedriver.exe"; System.setProperty("webdriver.chrome.driver", chromeDriverPath); //Goto guru99 site driver.get("http://slack.com/"); } @Test public void executSessionFour() throws MalformedURLException{ //Third session of WebDriver caps = new DesiredCapabilities(); caps.setCapability("os", "Windows"); caps.setCapability("os_version", "10"); caps.setCapability("browser", "Chrome"); caps.setCapability("browser_version", "80.0 beta"); caps.setCapability("browserstack.local", "false"); caps.setCapability("browserstack.selenium_version", "3.5.2"); caps.setCapability("name", "selenium test"); driver = new RemoteWebDriver(new URL(URL), caps); chromeOptions = new ChromeOptions(); String chromeDriverPath = "resources/chromedriver.exe"; System.setProperty("webdriver.chrome.driver", chromeDriverPath); //Goto guru99 site driver.get("http://yahoo.com/"); } @AfterTest public void browserclose (){ driver.quit(); System.out.println("TestCase : Browser was closed"); } }
testng.xml配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd" > <suite name="TestSuite" > <test name="testGuru" thread-count="4" parallel="methods"> <classes> <class name="selerixautomation.SecondNGTest"> </class> </classes> </test> </suite>
解决方案
这个问题我之前帮不少开发者解决过,核心是对TestNG注解生命周期和并行测试变量作用域的理解偏差,咱们一步步修正:
1. 换用正确的TestNG注解
@AfterTest:在整个<test>标签下的所有测试方法执行完成后仅运行一次,这就是为什么只有一个窗口被关闭的原因。@AfterMethod:在每个@Test方法执行完成后都会运行一次,完美匹配你每个测试方法对应一个浏览器窗口的场景。
2. 修正变量作用域
你把driver、caps等变量声明为static,这会导致多个并行线程共享同一个变量实例,后面的线程会覆盖前面的driver引用,最终只有最后一个driver被关闭。所以要移除static修饰符,让每个测试方法拥有独立的driver实例。
3. 移除冗余配置
你用的是RemoteWebDriver连接BrowserStack云端hub,完全不需要设置webdriver.chrome.driver系统属性(这是本地运行ChromeDriver才需要的),这部分代码是多余的,直接删掉即可。
4. 优化代码复用
把重复的DesiredCapabilities配置逻辑抽成公共方法,避免代码冗余,也方便后续统一修改配置。
修改后的完整代码
import org.openqa.selenium.WebDriver; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.remote.RemoteWebDriver; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import java.net.MalformedURLException; import java.net.URL; public class SecondNGTest { private WebDriver driver; private static final String USERNAME = "PRIVATE"; private static final String AUTOMATE_KEY = "PRIVATE"; private static final String URL = "https://" + USERNAME + ":" + AUTOMATE_KEY + "@hub-cloud.browserstack.com/wd/hub"; // 公共方法:创建并返回统一的BrowserStack配置 private DesiredCapabilities getBrowserStackCaps() { DesiredCapabilities caps = new DesiredCapabilities(); caps.setCapability("os", "Windows"); caps.setCapability("os_version", "10"); caps.setCapability("browser", "Chrome"); caps.setCapability("browser_version", "80.0 beta"); caps.setCapability("browserstack.local", "false"); caps.setCapability("browserstack.selenium_version", "3.5.2"); caps.setCapability("name", "selenium test"); return caps; } @Test public void executSessionOne() throws MalformedURLException { driver = new RemoteWebDriver(new URL(URL), getBrowserStackCaps()); driver.get("http://google.com/"); } @Test public void executeSessionTwo() throws MalformedURLException { driver = new RemoteWebDriver(new URL(URL), getBrowserStackCaps()); driver.get("http://youtube.com/"); } @Test public void executSessionThree() throws MalformedURLException { driver = new RemoteWebDriver(new URL(URL), getBrowserStackCaps()); driver.get("http://slack.com/"); } @Test public void executSessionFour() throws MalformedURLException { driver = new RemoteWebDriver(new URL(URL), getBrowserStackCaps()); driver.get("http://yahoo.com/"); } // 替换@AfterTest为@AfterMethod,每个测试方法结束后关闭对应driver @AfterMethod public void browserClose() { if (driver != null) { // 增加空判断,避免异常 driver.quit(); System.out.println("TestCase : Browser was closed"); } } }
保持testng.xml不变
你的testng.xml配置是正确的,parallel="methods"和thread-count="4"可以让4个测试方法并行执行,不需要修改。
这样修改后,每个测试方法执行完成后,对应的@AfterMethod都会触发,关闭当前方法的driver实例,所有浏览器窗口都会被自动关闭啦!
内容的提问来源于stack exchange,提问作者mastercool
相关产品推荐
相关产品推荐

