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!
我已经找到了解决方案:使用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()方法中所示,否则您可能会遇到空指针异常。感谢大家。