Как правильно реализовать пул драйверов Selenium в Java?

Я написал инструмент веб-автоматизации, используя Selenium WebDriver и geckodriver на Java. В настоящее время каждый раз, когда я выполняю задачу, создается новый объект FirefoxDriver.

Теперь я хочу реализовать многопоточность. Первый подход, который пришел мне в голову, заключался в создании чего-то вроде пула фиксированного размера — создавать экземпляры объектов X FirefoxDriver при запуске, оборачивать их в объект с флагом «inUse» и использовать синглтон для управления этими экземплярами.

Но правильное ли это решение? Это мой первый Selenium-проект, и вся концепция для меня нова. Я сам не смог найти ответ на этот вопрос после нескольких дней гугления и чтения документации. Я был бы очень признателен за вашу помощь!


person saxum    schedule 07.10.2016    source источник
comment
Рассматривали ли вы возможность использовать что-то вроде TestNG и позволить ему управлять пулом? С помощью настроек вы можете ограничить количество разрешенных потоков и т. д.   -  person JeffC    schedule 07.10.2016
comment
Я еще не рассматривал это, спасибо за подсказку! Я рассмотрю это для будущих задач веб-автоматизации.   -  person saxum    schedule 09.10.2016


Ответы (1)


Было бы вполне разумно создать такой пул. Вместо создания собственного пула я бы предложил использовать существующий универсальный пул, например классический Commons Pool. или более современный пул spf4j.

Чтобы пул работал, ваш код должен надежно возвращать драйвер в пул после использования, иначе произойдет утечка драйверов (и, следовательно, целых экземпляров браузера!).

Поэтому я бы рассмотрел другой подход: выделение драйвера для каждого потока. Это можно сделать с помощью ThreadLocal:

private ThreadLocal<WebDriver> drivers = new ThreadLocal<WebDriver>() {
    @Override
    protected WebDriver initialValue() {
        return new FirefoxDriver(); // or whatever
    }

    @Override
    public void remove() {
        WebDriver driver = get();
        if (driver != null) driver.close();
        super.remove();
    }

    @Override
    public void set(WebDriver value) {
        throw new UnsupportedOperationException();
    }
};

По-прежнему возможна утечка драйверов, но только если потоки умирают, не удаляя их значение из ThreadLocal. Если у вас есть фиксированный пул потоков, который вы повторно используете, все будет в порядке.

Недостатком этого подхода является то, что вы в конечном итоге получаете драйвер для каждого потока, который когда-либо использовал драйвер, даже если не каждый из этих потоков использует драйвер одновременно. Если у вас есть пул потоков, предназначенных для использования драйверов и мало чем еще занимающихся, то это не будет серьезной проблемой. Но если у вас есть пул потоков, которые выполняют много разных работ, это может быть.

person Tom Anderson    schedule 07.10.2016
comment
Но таким образом созданные окна браузера не будут переработаны, я думаю, что повторное использование однажды созданных окон сэкономит много времени. - person saxum; 07.10.2016
comment
Будет ли преимущество в использовании подхода ThreadLocal вместо использования Executors.newFixedThreadPool(n) и создания WebDriver внутри отправленного потока? - person saxum; 07.10.2016
comment
@saxum Пока каждый поток выполняет несколько тестов, драйверы и браузеры будут использоваться повторно. Вам действительно нужно объединить это с исполнителем, чтобы это произошло. - person Tom Anderson; 08.10.2016
comment
Попался, теперь понял. Это элегантное решение, большое спасибо! - person saxum; 09.10.2016