Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用并行线程测试Selenium_Java_Multithreading_Selenium Webdriver_Testng - Fatal编程技术网

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();
}