4

我有我的应用程序自动化,它有大约 70 多个脚本,并针对对其他应用程序开放的 Selenium Grid 运行。

我的问题是,有没有用于 WebDriver 的连接池 api?这样我就可以在我的脚本中有效地重新使用 webdriver 对象。我不希望我的脚本等待 IE 插槽并在无法获得时因超时错误而失败。

另外,我相信它会提高脚本执行的性能。

谢谢。

4

2 回答 2

3

我们的测试非常小而且速度非常快,以至于 webdrivers 的实例化时间比测试要长。所以我们汇集了网络驱动程序,就像@premganz 建议的那样,但是使用了 Apache Commons Pool。我们考虑编写自己的 webdriver 列表管理池,但发现使用完善的 Apache 池易于实现、健壮且可扩展。我们的测试同时运行 80 多个 WebDriver。

示例 WebdriverFactory:

public class WebdriverFactory extends BasePooledObjectFactory<RemoteWebDriver> {

    private FirefoxOptions firefoxOptions = new FirefoxOptions();

    public WebdriverFactory(boolean headless, int implicit_timeout_seconds) {
        super();
        firefoxOptions.setHeadless(headless)
                .setPageLoadStrategy(PageLoadStrategy.EAGER)
                .setLogLevel(FirefoxDriverLogLevel.ERROR);
    }

    @Override
    public RemoteWebDriver create() {
        FirefoxDriver webDriver = new FirefoxDriver(firefoxOptions);
        webDriver.manage()
                .timeouts()
                .implicitlyWait(implicit_timeout_seconds, TimeUnit.SECONDS);
        return webDriver;
    }

    /**
     * Use the default PooledObject implementation.
     */
    @Override
    public PooledObject<RemoteWebDriver> wrap(RemoteWebDriver webDriver) {
        return new DefaultPooledObject<>(webDriver);
    }

    /**
     * When a webdriver is returned to the pool, clean it up.
     */
    @Override
    public void passivateObject(PooledObject<RemoteWebDriver> webDriver) {
        WebDriver driver = webDriver.getObject();
        try {
            // close all tabs except the first
            String originalHandle = driver.getWindowHandle();
            for(String handle : driver.getWindowHandles()) {
                if (!handle.equals(originalHandle)) {
                    driver.switchTo().window(handle);
                    driver.close();
                }
            }
            driver.switchTo().window(originalHandle);
        } catch (Exception e) {
            // ...
        } finally {
            // ensure session data is not re-used
            driver.manage().deleteAllCookies();
        }
    }

    @Override
    public boolean validateObject(PooledObject<RemoteWebDriver> webDriver) {
        return true;
    }

    @Override
    public void activateObject(PooledObject<RemoteWebDriver> webDriver) throws Exception {
    }
}
于 2019-09-07T03:16:34.440 回答
0

我同意 WebDriver 池可以提高应用程序的性能。另一方面,如果您使用的是 selenium webdriver,则驱动程序将变为有状态的,从而使其可重用性降低。我做了这样的逻辑:

  1. 创建一个驱动程序工厂,它包装一个大小为 10 的链表(它实现了一个列表和一个队列)。

  2. 当被要求提供一个实例时,从列表中提供中间 (i==5) 一个

  3. 使用另一个线程回收队列中的驱动程序,从头部删除驱动程序并在尾部添加新驱动程序。

这样您就可以实现一个不断回收的池,并且您的代码不必阻塞在 driver.create 或 driver.quit 上。

于 2014-06-03T13:23:13.693 回答