多线程 Selenium WebDriver 与 Selenium Grid

Posted

技术标签:

【中文标题】多线程 Selenium WebDriver 与 Selenium Grid【英文标题】:Multi threaded Selenium WebDriver vs Selenium Grid 【发布时间】:2016-06-27 12:56:19 【问题描述】:

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

    控制器在多线程环境中启动 Selenium WebDriver(每个线程 1 个驱动程序实例,因为 WebDriver 不是线程安全的。参考:Selenium Grid, how to utilize WebDriver with ThreadSafeSeleniumSessionStorage.session()) 控制器使用 Selenium Grid

我了解 Selenium Grid 通过使用中心节点概念来支持分布式执行;但与选项 1 相比,我将获得哪些主要好处。

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

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

【问题讨论】:

这一切都取决于。您能否首先阐明您要实现的目标:您是否要测试多个浏览器/平台?您是否正在尝试进行负载测试?您是否只是想减少现有测试套件的持续时间?您计划/希望一次运行多少个会话(每台机器)? 【参考方案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-Safe、Full Guide 使用的版本: TestNG 6.14.3、Selenium 3.11、Selenium Grid 3.14.3 em>

此外,Selenium Grid 是否会负责清理其节点中的任何陈旧浏览器实例(开箱即用)?

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

【讨论】:

以上是关于多线程 Selenium WebDriver 与 Selenium Grid的主要内容,如果未能解决你的问题,请参考以下文章

译使用WebDriver采样器将JMeter与Selenium集成

与Python Scrapy中的Selenium WebDriver并发

线程“主”java.lang.NoClassDefFoundError 中的异常:org/openqa/selenium/WebDriver

python+selenium五:多窗口切换与获取句柄

Selenium WebDriver 在线程“main”org.openqa.selenium.ElementNotInteractableException 中抛出异常

我收到“线程“主”java.lang.NoClassDefFoundError:org/openqa/selenium/WebDriver 中的异常”