多线程Selenium WebDriver与Selenium Grid

时间:2016-03-12 06:18:03

标签: java multithreading selenium selenium-webdriver selenium-grid

我是Selenium的新手,我正在使用Selenium同时导航到同一网站的多个页面,同时保持会话。我可以通过以下两种方式创建控制器:

  1. 控制器在多线程环境中启动 Selenium WebDriver (每个线程1个驱动程序实例,因为WebDriver不是线程安全的。参考:Selenium Grid, how to utilize WebDriver with ThreadSafeSeleniumSessionStorage.session()
  2. 控制器使用 Selenium Grid
  3. 据我所知,Selenium Grid通过使用集线器节点概念支持分布式执行;但与选项1相比,我将获得哪些主要好处。

    我看到人们使用选项1,但面临一些问题。参考:Multiple WebDriver instances in Selenium without Grid?

    是否建议在多线程环境中使用Grid over Selenium WebDriver?如果是这样,为什么? 此外,Selenium Grid是否负责清理其节点中的任何过时的浏览器实例(开箱即用)?

1 个答案:

答案 0 :(得分:1)

我觉得您误解了WebDriver,Grid和多线程环境的目的。

Selenium WebDriver只是一个测试框架,可以在浏览器上启动测试。它使用诸如geckodriver和chromedriver之类的驱动程序来打开(和关闭)浏览器实例,然后通过操作命中这些实例。

Selenium Grid是一个独立服务器,它将在节点上远程运行WebDriver测试并进行报告。因此,如果您想使用其他机器资源来运行您的测试套件,则可以这样做。它还允许您通过为每个节点分配一个节点来组合多台计算机资源,Selenium Grid将平均分配您的测试。


关于您的多线程问题,

  

是否建议在多线程环境中使用 Grid over Selenium WebDriver?

Grid只是WebDriver的远程运行器。 WebDriver是测试框架。我假设您的目标是通过并行运行测试来减少测试套件的运行时间?并行测试可以使用WebDriver在本地计算机上进行,也可以在Selenium Grid上进行配置。根据我的经验,我在本地计算机上的运气比在Grid上的运气还好,但两者本质上都面临相同的问题。 使用WebDriver进行并行测试的主要危险是thread-safety JUnit 4.7及更高版本和Test-NG RELEASE允许进行并行测试。 为此,我强烈建议使用Test-NG代替JUnit。

为了防止并发问题,您的主要目标是使所有共享资源都隔离在每个线程中。第二个目标是将所有变量的范围限制为其方法。这可以使用ThreadLocal的静态实例来完成。强制将驱动程序实例的初始化冻结在同步方法中也非常有用。

创建资源

public class DriverFactory {

    private static String grid = "http://localhost:4444/wd/hub";
    public static ThreadLocal<WebDriver> drivers = new ThreadLocal<WebDriver>();

    public static synchronized void newDriver() {
        ChromeOptions options = new ChromeOptions(); // Assuming Chrome use
            options.addArguments("--start-maximized");

        // USE THIS FOR LOCAL
        // tlDriver.set(new ChromeDriver(options));

        // USE THIS FOR GRID
        try {
            drivers.set(new RemoteWebDriver(new URL(grid),options));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

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

测试类

public class GoogleTest {
    @BeforeMethod
    public void setup() {
         DriverFactory.newDriver();
    }

    @Test
    public void test1() {
        WebDriver driver = DriverFactory.getDriver();
        driver.navigate().to("https:\\www.google.com");
        Assert.assertEquals(driver.getTitle(), "Google");
    }

    @Test
    public void test2() {
        WebDriver driver = DriverFactory.getDriver();
        driver.navigate().to("https:\\www.google.com");
        Assert.assertEquals(driver.getTitle(), "Google");
    }


    @AfterMethod
    public void tearDown() {
        WebDriver driver = DriverFactory.getDriver();
        driver.quit();
    }
}

TestNG.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<!-- thread-count should be = to maxSessions on your Grid -->
<suite name="Whatever" parallel="methods" thread-count="5">
  <test name="Sample">
    <classes>
      <class name="GoogleTest"/>
    </classes>
  </test>
</suite>

来源Making your Tests Thread-SafeFull Guide
使用的版本 TestNG 6.14.3,Selenium 3.11,Selenium Grid 3.14.3

  

还有,Selenium Grid是否负责清理其节点中(开箱即用的)所有过时的浏览器实例?

Selenium Grid具有超时和browserTimeout功能,以释放节点并关闭浏览器实例。尽管以我的经验,我希望您控制测试用例中的任何预期超时,并让WebDriver关闭浏览器实例,而不是Selenium Grid。您真的想防止这种情况的发生,并消除导致意外挂起的所有原因。测试套件旨在提供快速反馈,并且仅在失败指示实际失败时才有用,而不仅仅是肮脏的测试套件。同样,过时的节点/浏览器也可能会迫使您不得不不断重置网格+节点,这是一个主要的不利因素。