Java 使用并行线程测试Selenium
我已经看到很多关于这个话题的问题,但似乎没有一个与我正在寻找的有关。我试图在单个类下运行并行方法,使用Java 使用并行线程测试Selenium,java,multithreading,selenium-webdriver,testng,Java,Multithreading,Selenium Webdriver,Testng,我已经看到很多关于这个话题的问题,但似乎没有一个与我正在寻找的有关。我试图在单个类下运行并行方法,使用@beforethod启动浏览器,使用@AfterMethod拆除浏览器。对于本例,我们只需假设它是一个类文件,其中包含多个测试方法。我希望在不同的浏览器中同时运行其中的4个。我们使用的是Groovy,但是一个Java答案就足够了 XML: 对于线程,也在DriverFactory类中: static final WebDriver createStackWebDriver(){ Thr
@beforethod
启动浏览器,使用@AfterMethod
拆除浏览器。对于本例,我们只需假设它是一个类文件,其中包含多个测试方法。我希望在不同的浏览器中同时运行其中的4个。我们使用的是Groovy,但是一个Java答案就足够了
XML:
对于线程,也在DriverFactory类中:
static final WebDriver createStackWebDriver(){
ThreadLocal<WebDriver> webDriver = new ThreadLocal<WebDriver>(){
protected WebDriver initialValue(){
createWebDriver()
}
}
webDriver.get()
}
当我们运行XML文件时,我们看到的是startUpWebBrowser()
的4个实例,其中一个将“通过”并继续测试,它将立即从startUpWebBrowser()
的一个实例中打开4个方法,而其他3个只是“挂起”。我们需要它在每个startUpWebBrowser()
实例中打开一个浏览器,而不是在一个实例中打开4个浏览器
我们当前的解决方法是将每个@Test
方法包装在自己的类中,并将@beforethod
以及after更改为@BeforeClass
。这在某种程度上是可行的,但在报告方面非常丑陋,而且这种方式还有其他一些缺点
在不彻底检查当前体系结构的情况下,有没有解决这个问题的方法?我是不是遗漏了一些非常简单的东西?问题在于您的测试类
TestPlatform
,其中您正在将webdriver实例变量保存到类级数据成员webdriver webdriver
因此,当两个或多个@Test
方法并行运行时,所有方法实际上都试图将webdriver实例分配给相同的webdriver
实例
请按如下方式修复它
class TestPlatform {
@BeforeMethod
void startUpWebBrowser(){
DriverFactory.createStackWebDriver()
//Access webdriver instances only via DriverFactory.createStackWebDriver()
}
@AfterMethod
void quitWebDriver(){
DriverFactory.createStackWebDriver().quit()
}
}
问题在于您的测试类
TestPlatform
,其中您正在将webdriver实例变量保存到类级数据成员webdriver webdriver
因此,当两个或多个@Test
方法并行运行时,所有方法实际上都试图将webdriver实例分配给相同的webdriver
实例
请按如下方式修复它
class TestPlatform {
@BeforeMethod
void startUpWebBrowser(){
DriverFactory.createStackWebDriver()
//Access webdriver instances only via DriverFactory.createStackWebDriver()
}
@AfterMethod
void quitWebDriver(){
DriverFactory.createStackWebDriver().quit()
}
}
似乎是
ThreadLocal
误用。我将使用以下代码段:
private static final ThreadLocal<WebDriver> DRIVER_CONTAINER = new ThreadLocal<>();
@BeforeMethod
void startUpWebBrowser(){
DRIVER_CONTAINER.set(createWebDriver());
}
@AfterMethod
void quitWebDriver(){
ofNullable(getDriver()).ifPresent(WebDriver::quit);
DRIVER_CONTAINER.remove();
}
public static WebDriver getDriver() {
return DRIVER_CONTAINER.get();
}
private static final ThreadLocal DRIVER_CONTAINER=new ThreadLocal();
@预处理法
void startUpWebBrowser(){
DRIVER_CONTAINER.set(createWebDriver());
}
@后置法
void quitWebDriver(){
ofNullable(getDriver()).ifPresent(WebDriver::quit);
驱动程序_容器。移除();
}
公共静态WebDriver getDriver(){
返回驱动程序_CONTAINER.get();
}
或者只是将驱动程序管理部分移动到
IInvokedMethodListener
似乎是ThreadLocal
误用。我将使用以下代码段:
private static final ThreadLocal<WebDriver> DRIVER_CONTAINER = new ThreadLocal<>();
@BeforeMethod
void startUpWebBrowser(){
DRIVER_CONTAINER.set(createWebDriver());
}
@AfterMethod
void quitWebDriver(){
ofNullable(getDriver()).ifPresent(WebDriver::quit);
DRIVER_CONTAINER.remove();
}
public static WebDriver getDriver() {
return DRIVER_CONTAINER.get();
}
private static final ThreadLocal DRIVER_CONTAINER=new ThreadLocal();
@预处理法
void startUpWebBrowser(){
DRIVER_CONTAINER.set(createWebDriver());
}
@后置法
void quitWebDriver(){
ofNullable(getDriver()).ifPresent(WebDriver::quit);
驱动程序_容器。移除();
}
公共静态WebDriver getDriver(){
返回驱动程序_CONTAINER.get();
}
或者只需将驱动程序管理部分移动到
IInvokedMethodListener
测试平台中的webdriver变量不是线程安全的。将ThreadLocal变量作为静态final移动到TestPlatform类中,并在initialValue方法中调用DriverFactory.createWebDriver()不是更简单吗。不需要beforemethod,因为您可以在测试方法中的threadlocal变量上使用get()获取特定于线程的驱动程序。此外,您还有一个用于驱动程序quit方法的shutdownhook,以及aftermethod中的quit调用。aftermethod也可以删除。TestPlatform中的webdriver变量不是线程安全的。将ThreadLocal变量作为静态final移动到TestPlatform类中,并在initialValue方法中调用DriverFactory.createWebDriver()不是更简单吗。不需要beforemethod,因为您可以在测试方法中的threadlocal变量上使用get()获取特定于线程的驱动程序。此外,您还有一个用于驱动程序quit方法的shutdownhook,以及aftermethod中的quit调用。aftermethod也可以删除。
private static final ThreadLocal<WebDriver> DRIVER_CONTAINER = new ThreadLocal<>();
@BeforeMethod
void startUpWebBrowser(){
DRIVER_CONTAINER.set(createWebDriver());
}
@AfterMethod
void quitWebDriver(){
ofNullable(getDriver()).ifPresent(WebDriver::quit);
DRIVER_CONTAINER.remove();
}
public static WebDriver getDriver() {
return DRIVER_CONTAINER.get();
}