一尘不染

Java中的静态Webdriver实例同步

selenium

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控件上执行一些操作(此类也使用全局变量),例如:

public class GetLabelProperties extends GlobalVariables
{
public static String getLabelText(WebElement element)
{
return element.getText();
}
}

public class PerformAction extends GlobalVariables
{
public static void setText(String textBoxName,String someText)
{
driver.findElement(someLocator(textBoxName)).setText("someText");
}
    //Some other methods which may or may not use the global variables to perform some action
}

我在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)使用同步。2)创建ThreadLocal实例(注意:我已经尝试过此解决方案,但仍然是同样的问题。测试相互混合会导致失败。我已将WebDriver实例标记为ThreadLocal,并重写了ThreadLocal的initialValue方法来初始化驱动程序实例。我仍然不确定我是否正确实施了它。)。现在,我不确定在给定场景下如何最好地实现此解决方案中的任何一个。任何帮助表示赞赏。TIA!


阅读 278

收藏
2020-06-26

共1个答案

一尘不染

我已经找到了解决方案:使用ThreadLocal是在大型多线程环境中运行测试的最佳解决方案。在多线程环境中使用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.
                    }
                };

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

2020-06-26