使用TestNG运行并行测试时如何避免空的额外浏览器打开

时间:2016-01-06 19:06:21

标签: browser parallel-processing webdriver testng

当我使用TestNG和selenium-webdriver运行并行测试用例时,有些浏览器实例打开为空,即使在执行完成后也不会关闭。我在不同的论坛上阅读了几个主题,询问类似的问题,但似乎没有一个问题是同一个问题。

当我向套件中添加更多测试时,似乎还会打开更多空的浏览器。我不确定以下哪些信息与此问题有关,但我会尽力提供我所拥有的完整图片:

  • 我正在使用(如上所述)TestNG - webdriver。
  • 我正在处理页面对象模式。
  • 我从javafx界面运行自动化,允许用户选择一些选项。
  • 我正在使用ChromeDriver来模拟移动设备。
  • 我正在使用驱动程序的本地线程,这允许我为每个测试使用独有的静态驱动程序。
  • 当我没有并行运行时,没有空的浏览器打开。

这是我的TestNg.xml:

<suite name="Suite" parallel="classes" thread-count="4">
<test name="Test">
<groups>
     <run>
        <!-- Use include to specify what you want to run or exclude to not run the mentioned group(s) -->
        <include name="fullRegression"/>
        <exclude name="brokenOrDevelopment"/>
     </run>
  </groups>
<packages>
    <!-- Packages who contains the test cases classes -->
    <package name="Test"/>       
</packages>

 

这是创建驱动程序实例的类

public class TestCaseConfiguration {
 protected HomePageObjects homePage = null;
 protected DesiredCapabilities  capabilities;
 protected ExtentReports REPORTMANAGER;
 protected ExtentTest REPORT;

 public static ThreadLocal<ChromeDriver> driver;

 @BeforeMethod(alwaysRun = true)
 public void setup() throws InterruptedException {

     System.setProperty("webdriver.chrome.driver", "src/Tools/chromedriver.exe");//chrome driver version 2.20 | We need to have a relative path since no all the user will have the driver on C: 

     capabilities = DesiredCapabilities.chrome();
     Map<String, String> mobileEmulation = new HashMap<String, String>();
     mobileEmulation.put("deviceName", Constants.DEVICE);
     Map<String, Object> chromeOptions = new HashMap<String, Object>();
     chromeOptions.put("mobileEmulation", mobileEmulation);

     capabilities.setCapability(ChromeOptions.CAPABILITY, chromeOptions);

     /**
      * dirver is a ThreadLocal<ChromeDriver>. This allows the driver to be static and available for the complete project, and exclusive for each thread. 
      */
     driver=new ThreadLocal<ChromeDriver>()
                {
                    @Override
                    protected ChromeDriver initialValue()
                    {
                        return new ChromeDriver(capabilities); 
                    }
                };
     driver.get().manage().deleteAllCookies();
     driver.get().manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
     driver.get().navigate().to(Constants.DOMAIN);

     homePage = PageFactory.initElements(driver.get(), HomePageObjects.class);
 }

 @AfterMethod(alwaysRun = true)
 public void close() throws InterruptedException {           
    driver.get().close();
    driver.get().quit();  
 }

}

此类由每个测试用例类扩展。测试按预期运行,唯一的问题似乎是额外的浏览器实例。

没有人知道如何避免这个问题或者我做错了什么? 谢谢你的帮助。

This is how the browser looks when open empty

2 个答案:

答案 0 :(得分:2)

您正在创建新的ThreadLocal<ChromeDriver>实例,并在每次driver运行时重新分配setup。想象一下以下场景:多个线程并行调用setup

  1. Thread0创建ThreadLocal<ChromeDriver>个实例,将其分配给driver,然后调用driver.get()。一个浏览器现已打开。
  2. Thread1创建一个ThreadLocal<ChromeDriver>实例,将其分配给driver(替换Thread0分配给它的那个),然后调用driver.get()。现在有两个浏览器打开,每个ThreadLocal实例一个。
  3. Thread0再次调用driver.get(),但driver不再引用相同的ThreadLocal实例,因此会打开一个新的浏览器。现在有三个浏览器处于打开状态,一个位于“孤立”ThreadLocal实例中,两个位于引用的ThreadLocal中。
  4. 现在想象一下这个场景,但有两个以上的线程!你会有很多“孤立的”ThreadLocal个实例浮动,其中一些实例与一些线程有一个ChromeDriver实例但在任何线程上都没有对象引用{{1}为了“得到”他们。

    要解决此问题,我建议将ThreadLocal标记为driver并为其分配final个实例。

    e.g。

    ThreadLocal

答案 1 :(得分:0)

我在libFile中创建了单独的方法,我在每个测试用例中调用它。 @Libraryfile

//Variable declaration
WebDriver driver=null;

protected WebDriver getDriverInstance(){
   driver=new FirefoxDriver();
   return driver;
}

@testcase类 - 我在@BeforeMethod上调用上面的方法     //变量声明

WebDriver driver=null;

@BeforeMethod
public void setUp(){
 driver=getDriverInstance();

}

这解决了我的多个空浏览器实例