Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.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中的静态Webdriver实例同步_Java_Selenium_Selenium Webdriver_Testng_Synchronized - Fatal编程技术网

java中的静态Webdriver实例同步

java中的静态Webdriver实例同步,java,selenium,selenium-webdriver,testng,synchronized,Java,Selenium,Selenium Webdriver,Testng,Synchronized,GlobalVariables类包含在我的框架中使用的不同变量,其中一个是WebDriver实例: public class GlobalVariables { public static WebDriver driver; //Some other static global variables required across my framework public GlobalVariables(String propertiesF

GlobalVariables类包含在我的框架中使用的不同变量,其中一个是WebDriver实例:

  public class GlobalVariables
        {
        public static WebDriver driver;
    //Some other static global variables required across my framework
        public GlobalVariables(String propertiesFile)
        {
        initializeVariables(propertiesFile);
        }
        public void initializeVariables(String propertiesFile)
        {
        GlobalInitializer obj=new GlobalInitializer();
        obj.initialize(String propertiesFile);
        }
   }
GlobalInitializer包含初始化所有GlobalVariable的方法:

public class GlobalInitializer extends GlobalVariables
{
public void initialize(String propertiesFile)
{
  //Some logic to read properties file and based on the properties set in it, call other initialization methods to set the global variables.
}
public void initializeDriverInstance(String Browser)
{
driver=new FireFoxDriver();
}
//初始化其他全局变量的一些其他方法。 }

我有许多GetElement类,它们使用驱动程序实例来获取UI控制元素,例如:

public class GetLabelElement extends GlobaleVariables
{
public static WebElement getLabel(String someID)
{
return driver.findElement(By.id(someId));
}
//Similar methods to get other types of label elements.
}

public class GetTextBoxElement extends GlobaleVariables
{
public static WebElement getTextBox(String someXpath)
{
return driver.findElement(By.xpath(someXpath));
}
//Similar methods to get other types of text box elements.
}
我还有其他类在UI控件上执行一些操作(这些类也使用全局变量),例如:

我在testng中的测试类如下所示:

public class TestClass
{
GlobalVariables globalObj=new GlobalVariables(String propertiesFile);
@Test(priority=0)
{
GlobalVariables.driver.get(someURL);
//Some assertion.
}
@Test(priority=1)
{
WebElement element=GetLabelElement.getLabel(someID);
String labelName=GetLabelProperties.getLabelText(element);
//Some assertion.
}
@Test(priority=2)
{
WebElement element=GetTextBoxElement.getTextBox(someXpath);
PerformAction.setText(element.getText(),someText);
//Some assertion.
}
}
我有基于场景的类似多个测试类。
现在,如果我单独运行这些测试,它们运行得很好。但当我尝试并行运行它们时,这些测试以某种奇怪的方式失败了。通过分析,我发现是静态全局变量,每个测试都会初始化这些变量,从而导致其他测试失败。现在,我应该如何着手实现我的目标,在我的框架设计中以最小的变化并行运行多个测试?我尝试过搜索选项,我遇到了一些选项,例如1)使用synchronized。2) 创建线程本地实例(注意:我尝试过此解决方案,但仍然存在相同的问题。测试相互混淆,导致失败。我已将WebDriver实例标记为ThreadLocal,并重写ThreadLocal的initialValue方法以初始化驱动程序实例。但我仍不确定是否正确实现了它。)。现在我不确定如何在给定场景中最好地实现此解决方案中的任何一个。非常感谢您的帮助。TIA!

您之所以能够获得此帮助,是因为JVM处理静态成员和方法的方式

如果要并行运行,就不能有静态webdriver对象


来源:我在工作的地方实现的自动回归系统-我们遇到了这个问题。

如果要非并行运行,则使用静态webdriver成员(或通过引用传递在测试类之间共享的实例)这很好,因为这是一种不必在测试类之间关闭webdriver实例的好方法。但是,如果要并行运行,则每个线程需要一个webdriver实例,因此在这种情况下,使用静态成员是错误的做法。相反,当测试用例类关闭时,需要创建或传递webdriver实例调用


此外,您正在将测试的每个步骤分解为单独的测试。这是非常不寻常的,我看不出您这样做的原因。您可以像人们通常做的那样将所有测试步骤放在一个单独的测试用例中,从而真正简化您的测试。

我找到了解决方案:使用ThreadLocal I这是在大型多线程环境中运行测试的最佳解决方案。 在多线程环境中使用WebDriver的代码段:

public static ThreadLocal<WebDriver> driver;
driver=new ThreadLocal<WebDriver>()
                {
                    @Override
                    protected WebDriver initialValue()
                    {
                        return new FirefoxDriver(); //You can use other driver based on your requirement.
                    }
                };
公共静态线程本地驱动程序;
驱动程序=新线程本地()
{
@凌驾
受保护的WebDriver initialValue()
{
返回新的FirefoxDriver();//您可以根据需要使用其他驱动程序。
}
};

现在,每次创建一个测试线程时,都会打开一个新浏览器。ThreadLocal将确保每个线程只有一个静态webdriver实例副本。[注意:确保您的其他全局变量太ThreadLocals。在我的情况下,它们不是ThreadLocals。这就是我遇到测试出错问题的原因]。我想与大家分享一些额外的知识,以便其他人能从中获益。在ThreadLocal中,每当调用ThreadLocal.get()方法时,您必须确保有一个初始化线程本地的规定,如上面的initialValue()所示方法,否则您可能会遇到空指针异常。谢谢大家。

您可以尝试类似的方法

公共类驱动程序管理器{

private static final ThreadLocal<WebDriver> threadLocal = new ThreadLocal<WebDriver>();

public static WebDriver getDriver() {
    return threadLocal.get();
}

public static void setDriver(WebDriver driver) {
    threadLocal.set(driver);
}

public static void closeDriver() {
    if (getDriver() != null) {
        try {
            getDriver().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            getDriver().quit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    threadLocal.remove();
}
private static final ThreadLocal ThreadLocal=new ThreadLocal();
公共静态WebDriver getDriver(){
返回threadLocal.get();
}
公共静态无效设置驱动程序(WebDriver驱动程序){
threadLocal.set(驱动程序);
}
公共静态void closeDriver(){
如果(getDriver()!=null){
试一试{
getDriver().close();
}捕获(例外e){
e、 printStackTrace();
}
试一试{
getDriver().quit();
}捕获(例外e){
e、 printStackTrace();
}
}
threadLocal.remove();
}

}

首先,我更喜欢一种简单的“命名和目录”模式来共享全局变量,我不喜欢你的解决方案从glob var类扩展!因此,使用接口(代理)您可以在并行情况下管理系统。根据我在javadocs中的搜索和阅读,我发现可以使用ThreadLocal来实现这一点。现在纠正我的错误,ThreadLocal确保每个线程只有一个驱动程序实例在运行(即,对于多个线程,创建多个驱动程序(或浏览器)实例)。并且一个线程的驱动程序实例不会与另一个线程中运行的另一个实例混淆。对吗?请注意,我有一个非常庞大的应用程序要测试,因此我将不得不按照我的上述设计,在粒度级别上,为了方便使用,我不会使用ThreadLocal,因为您的测试框架正在进行分叉和线程处理(即TestNG、Maven-Surefire、Gradle或其他)。如果您想手工编写自己的线程处理和测试分叉,那么您这么做很可能是因为您不了解正确的Selenium设计模式,或者您太先进/知识渊博,以至于您头脑中有一个需要它的特殊情况。您能展示更完整的代码结构吗?我似乎做不到使用ThreadLocal工作。我喜欢这个想法,但我行为不端,并对浏览器实例进行垃圾邮件处理,甚至更多
private static final ThreadLocal<WebDriver> threadLocal = new ThreadLocal<WebDriver>();

public static WebDriver getDriver() {
    return threadLocal.get();
}

public static void setDriver(WebDriver driver) {
    threadLocal.set(driver);
}

public static void closeDriver() {
    if (getDriver() != null) {
        try {
            getDriver().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            getDriver().quit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    threadLocal.remove();
}