Есть ли способ получать файлы из теста выполняемого на удаленном драйвере?

У меня на одной машине запускается java-код с selenium тестом. Но, браузер в котором выполняется тест - запускается в docker-контейнере, который запущен на другой машине. Организовано это при помощи RemoteWebDriver.
Я нашел решение проблемы для File Uploads. Чтобы получилось загружать файлы в браузере, который в контейнере, прямо с локальной машины где запущен java-код, нужна настройка driver.setFileDetector(new LocalFileDetector());.
Вопрос, как организоваться File downloads? Чтобы когда тест нажимал в браузере в контейнере на кнопку “Скачать” у файла. Он загрузился не в контейнере, а там где выполняется java-код. Хочу организовать всю работу с файлами локально, а не в контейнере. Контейнер нужен только для изоляции выполнения теста в браузере.
Или подскажите какие решения используете вы.

Сделай mount/volume папки в контейнере и папки с тестами

1 лайк

Я думаю что вы не правильно поняли вопрос. Я постарался более детально его описать.

Вы неверно поняли ответ :slight_smile: Именно этот механиз и используется для работы с File downloads. Прокиньте папку в которую сохраняются файлы (она или папка “по умолчанию” или прописана в конфигах) на свою машину где запускается код и работайте “локально”.

1 лайк

В Selenide реализованы три варианта скачивания файла, которые могут работать и в контейнере. Берите готовое решение и не изобретайте велосипед :slight_smile:

2 лайка

Если используется Selenoid - то можно скачивать через специальное API:

1 лайк

Хочу использовать Selenide решение, но сталкиваюсь с ошибкой.

 java.lang.IllegalStateException: config.proxyEnabled == true but proxy server is not created. You need to call `setWebDriver(webDriver, selenideProxy)` instead of `setWebDriver(webDriver)` if you need to use proxy.

Насколько я понял, такой ошибки не должно возникать и должно хватать объявлений

Configuration.proxyEnabled = true;
Configuration.fileDownload = PROXY;

Версию selenide использую последнюю. Что может быть не так?

Возможно, вы задаёте Configuration.proxyEnabled = true; ПОСЛЕ того, как открыли браузер. А надо ДО.

Ну и вообще, тут важно, открываете ли вы браузер сами, или это делает селенид?

1 лайк

Пробовал сделать как вы подсказали тут Как правильно связать Selenide и Selenium Grid? - #11 от пользователя asolntsev , но получил ту же ошибку.

Мой код:

HashMap<String, Object> chromePrefs = new HashMap<>();
chromePrefs.put("profile.default_content_settings.popups", 0);
chromePrefs.put("download.prompt_for_download", false);
chromePrefs.put("download.default_directory", ConfigContainer.getInstance().getPathToTempFolderWithRandomName());
ChromeOptions options = new ChromeOptions();
options.addExtensions(new File(drivers + "CryptoCades.crx"));
options.setExperimentalOption("prefs", chromePrefs);
options.addArguments("--start-maximized");

DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setBrowserName("chrome");
capabilities.setVersion("gost");
capabilities.setCapability("enableVNC", true);
capabilities.setCapability("enableVideo", false);
capabilities.setCapability(ChromeOptions.CAPABILITY, options);

Configuration.selectorMode = SelectorMode.Sizzle;
Configuration.pollingInterval = 50;
Configuration.proxyEnabled = true;
Configuration.fileDownload = PROXY;

RemoteWebDriver driver = new RemoteWebDriver(
       URI.create("http://localhost:4444/wd/hub").toURL(),
       capabilities
);

driver.setFileDetector(new LocalFileDetector());
WebDriverRunner.setWebDriver(driver);
timeout = 30000;

open("https://yandex.ru");

Браузер запускается при создании RemoteWebDriver, конфигурация объявлена до этого.
При вызове open() получаю ошибку.

java.lang.IllegalStateException: config.proxyEnabled == true but proxy server is not created. You need to call `setWebDriver(webDriver, selenideProxy)` instead of `setWebDriver(webDriver)` if you need to use proxy.

А, ну так конечно.
Мы же сами открываете браузер (new RemoteWebDriver) и передаёте его селениду. И открываете его без прокси. В итоге ваш браузер ничего не знает про селенидовский прокси.

Идеальный вариант - не использовать метод WebDriverRunner.setWebDriver(driver);.

См. setWebDriver или WebDriverProvider?

1 лайк

Вроде получилось, но проблема что при запуске браузера нет интернета… Прокси же сам должен настроиться? Т.е. Selenide запускает собственный «встроенный» прокси-сервер на той же машине, где выполняются тесты. Может данный прокси из коробки не подходит в моём случае, где я подключаюсь к удаленному контейнеру через туннель(vpn).
И WebDriverRunner не могу использовать для установки прокси - билд тогда падает.

Код
    private void setRemoteDriver(){
        Configuration.selectorMode = SelectorMode.Sizzle;
        Configuration.pollingInterval = 50;
        Configuration.proxyEnabled = true;
        Configuration.fileDownload = PROXY;
        Configuration.browser = MyWebDriverProvider.class.getName();
    }

    private static class MyWebDriverProvider implements WebDriverProvider {
        @Override
        public WebDriver createDriver(DesiredCapabilities capabilities) {
            String drivers = ConfigContainer.getInstance().getConfigPropertyWithEncode("ExternalDriverPath");
            HashMap<String, Object> chromePrefs = new HashMap<>();
            chromePrefs.put("profile.default_content_settings.popups", 0);
            chromePrefs.put("download.prompt_for_download", false);
            ChromeOptions options = new ChromeOptions();
            options.addExtensions(new File(drivers + "CryptoCades.crx"));
            options.setExperimentalOption("prefs", chromePrefs);
            options.addArguments("--start-maximized");
            capabilities.setBrowserName("chrome");
            capabilities.setVersion("gost");
            capabilities.setCapability("enableVNC", true);
            capabilities.setCapability("enableVideo", false);
            capabilities.setCapability(ChromeOptions.CAPABILITY, options);

            try {
                return new RemoteWebDriver(new URL("http://localhost:4444/wd/hub"), capabilities);
            }
            catch (MalformedURLException e) {
                throw new RuntimeException(e);
            }
        }
    }
Лог билда
2020-09-01 17:52:26 [INFO] - No webdriver is bound to current thread: 1 - let's create a new webdriver
2020-09-01 17:52:27 [INFO] - Starting proxy at address: 0.0.0.0/0.0.0.0:0
2020-09-01 17:52:27 [INFO] - Proxy listening with TCP transport
2020-09-01 17:52:28 [INFO] - Proxy started at address: /0:0:0:0:0:0:0:0:58983
2020-09-01 17:52:28 [INFO] - Creating folder: D:\PROJECTS\test_docker\build\downloads\1598971948014_11920_1
сен 01, 2020 5:52:37 PM org.openqa.selenium.remote.ProtocolHandshake createSession
INFO: Detected dialect: W3C
2020-09-01 17:52:37 [INFO] - Set browser size to 1366x768
2020-09-01 17:52:37 [INFO] - BrowserName=chrome Version=81.0.4044.138 Platform=LINUX
2020-09-01 17:52:37 [INFO] - Selenide v. 5.14.2
2020-09-01 17:52:37 [INFO] - Selenium WebDriver v. 3.141.59 build time: 2018-11-14T08:17:03
2020-09-01 17:52:37 [INFO] - Create webdriver in current thread 1: RemoteWebDriver -> RemoteWebDriver: chrome on LINUX (a05e0a686fde5032373bb2e6b13192e4)
Скрин результата

Конечно же, для работы прокси необходимо, чтобы машина с тестами (на которой запускается и прокси) была доступна с той машины/контейнера, где запускается браузер. Если нужно прокинуть порт или туннель - ну да, придётся прокинуть. Без этого прокси не взлетит (“не будет интернета”).

1 лайк

Не могу понять как сделать чтобы машина с тестами была доступна с контейнера. Понял что прокси-сервер запускается на машине рядом с запущенным тестом. Нашел как зафиксировать порт Configuration.proxyPort = 30001;.
Пробовал добавлять этот порт при запуске контейнера -p 30001:30001, но тогда тест падает при запуске прокси-сервера, т.к. порт уже занят(тот что первый).
Пробовал прописать его в Environment в docker-compose.
Пробовал chrome_options.addArgument("--proxy-server=localhost:30001").
Как именно открыть/прокинуть нужный доступ?

Дык, а я сам не знаю. :slight_smile:
Никогда этого не делал. Может, коммьюнити поможет?

Вопрос решился) Создал экземпляр Proxy, указал в нём хост и порт прокси-сервера, который создал Selenide, и передал его в capabilities драйверу. экспериментировал развернув контейнер локально. Сложность была в том что я хост указывал localhost, а из контейнера он указывается как host.docker.internal. Надо будет ещё правильно задать его когда контейнер будет в другой сети под vpn.
Возникла сложность с методом download(). Так как при нажатии на кнопку вызывался ряд запросов. Решением было создать и передать параметром FileFilter :+1:

1 лайк

В итоге использование решения с методом download() и прокси-сервером не подошло.

  1. Через прокси идёт весь трафик, а это сильно замедляет тест. Как использовать иначе способа не нашел. Может вы подскажите… Я где-то на просторах читал ваше сообщение, где вы писали что прокси не замедляет тест. Может вы имели ввиду что потери минимальны. Но когда между тестом с прокси и контейнером с вебдрайвером расстояние тысяча километров, тогда потери скорости очень ощутились :frowning:
  2. Прокси подменяет сертификат из-за чего пропадает возможность работать с гостовыми сайтами.

Использование прокси вызывает интерес, если возможно решить эти две проблемы. С сертом. И чтобы к примеру весь трафик шел напрямую, а вот именно скачивание файлов через прокси.

  1. Это правда: я говорил, что прокси не замедляет тесты. Но да, имелся в виду локальный запуск тестов. И конечно, имелось в виду, что замедление не равно нулю, а крайне мало. А при удалённом запуске наверняка замедление может быть и больше, да.

P.S. Но зачем запускать браузеры за тысячу километров, я вообще не понимаю, вне зависимости от прокси.

  1. Проблема с сертификатом наверняка решается так, что браузеру при открытии можно добавить сертификат прокси в список доверенных сертификатов. Но я сам это ещё не пробовал.
1 лайк