Selenium Marionette driver UnreachableBrowserException при втором запуске
В настоящее время я играю с марионеткой Селена WebDriver
. В моем приложении я хочу открыть несколько драйверов Marionette последовательно. В основном что-то вроде этого:
MarionetteDriver driver = new MarionetteDriver();
// do some stuff
driver.quit();
// a while later
driver = new MarionetteDriver();
// do some stuff
driver.quit();
Теперь я сталкиваюсь с проблемой, что только первый экземпляр марионетки может быть успешно запущен, и для каждой последующей попытки я получаю следующее исключение. Проблема происходит каждый раз, и используемый порт всегда меняется, поэтому, очевидно, нет порта конфликт.
Exception in thread "main" org.openqa.selenium.remote.UnreachableBrowserException: Could not start a new session. Possible causes are invalid address of the remote server or browser start-up failure.
Build info: version: '2.48.2', revision: '41bccdd10cf2c0560f637404c2d96164b67d9d67', time: '2015-10-09 13:08:06'
System info: host: 'qqilihq.local', ip: '192.168.1.2', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.11.2', java.version: '1.7.0_71'
Driver info: driver.version: MarionetteDriver
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:641)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:247)
at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:232)
at org.openqa.selenium.firefox.MarionetteDriver.run(MarionetteDriver.java:84)
at org.openqa.selenium.firefox.MarionetteDriver.<init>(MarionetteDriver.java:73)
at org.openqa.selenium.firefox.MarionetteDriver.<init>(MarionetteDriver.java:45)
at MyMainClass.main(MyMainClass.java:131)
Caused by: org.openqa.selenium.WebDriverException: org.apache.http.conn.HttpHostConnectException: Connect to localhost:41886 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused
Build info: version: '2.48.2', revision: '41bccdd10cf2c0560f637404c2d96164b67d9d67', time: '2015-10-09 13:08:06'
System info: host: 'qqilihq.local', ip: '192.168.1.2', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.11.2', java.version: '1.7.0_71'
Driver info: driver.version: MarionetteDriver
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:91)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:620)
... 6 more
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:41886 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:151)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:71)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
at org.openqa.selenium.remote.internal.ApacheHttpClient.fallBackExecute(ApacheHttpClient.java:143)
at org.openqa.selenium.remote.internal.ApacheHttpClient.execute(ApacheHttpClient.java:89)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:142)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:82)
... 7 more
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:74)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator. java:134)
... 20 more
любой указатели с благодарностью!
4 ответов
копнув немного глубже, я пришел к следующим выводам, которые в конечном итоге решили мою проблему:
-
марионеток респ.
wires
использует два порта (см.wires --help
); amarionette-port
иwebdriver-port
:Usage: ./wires [OPTIONS] WebDriver to marionette proxy. optional arguments: -h,--help show this help message and exit -b,--binary BINARY Path to the Firefox binary --webdriver-host WEBDRIVER_HOST Host to run webdriver server on --webdriver-port WEBDRIVER_PORT Port to run webdriver on --marionette-port MARIONETTE_PORT Port to run marionette on --connect-existing Connect to an existing firefox process
при запуске нескольких
MarionetteDrivers
одновременно, оба порта должны отличаться от уже запущенного экземпляра, очевидно. Однако, при использовании конструктора по умолчаниюnew MarionetteDriver()
наmarionette-port
остается постоянным (и не определяется на основе на каком-то свободном порту). Мы использовали некоторые обходные пути (см. ниже) дляGeckoDriverService.Builder
всегда выбирать два случайно выбранных доступных порта. текущий (версия 2.48.2)
GeckoDriverService
имеет пустую реализациюwaitUntilAvailable()
(который должен проверить, еслиWebDriver
готово к работе). Спорадически это приводит кUnreachableBrowserException
выложил выше.
чтобы обойти эти вопросы, мы сделали что-то вроде этого в конце:
// determine free ports for Marionette and WebDriver
final int marionettePort = PortProber.findFreePort();
final int webDriverPort = PortProber.findFreePort();
// override, as GeckoDriverService provides no direct way to set the Marionette port
GeckoDriverService.Builder builder = new GeckoDriverService.Builder() {
@Override
protected ImmutableList<String> createArgs() {
Builder<String> argsBuilder = ImmutableList.builder();
argsBuilder.addAll(super.createArgs());
argsBuilder.add(String.format("--marionette-port=%d", marionettePort));
return argsBuilder.build();
}
};
builder.usingPort(webDriverPort);
builder.usingDriverExecutable(pathToDriver);
GeckoDriverService driverService = builder.build();
try {
driverService.start();
} catch (IOException e) {
throw new IllegalStateException("Could not start the GeckoDriverService", e);
}
try {
// keep checking the WebDriver port via Socket until it's available;
// as far as I could tell, there is nothing more "high level", e.g. REST API
waitUntilReady(webDriverPort, TimeUnit.SECONDS.toMillis(30));
} catch (InterruptedException e) {
// ignore
}
return new MarionetteDriver(driverService, capabilities);
вам нужно обработать двоичный файл, требуемый марионеткой. Вы можете сделать это вручную (загрузить двоичный файл самостоятельно и экспортировать соответствующую переменную), или вы можете сделать это автоматически, используя WebDriverManager. Просто добавьте следующую зависимость:
<dependency>
<groupId>io.github.bonigarcia</groupId>
<artifactId>webdrivermanager</artifactId>
<version>1.6.0</version>
</dependency>
и затем, в вашем коде вызовите:
FirefoxDriverManager.getInstance().setup();
в основном UnreachableBrowserException
происходит, когда Selenium не может найти требуемый exe драйвера. Поскольку вы не поставили настройку возможностей драйвера, я предполагаю, что следующие шаги решат вашу проблему.
согласно Mozilla MDN ссылке марионетка устанавливается как DesiredCapability
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
// Set Marionette on so the Grid will use this instead of normal FirefoxDriver
capabilities.setCapability("marionette", true);
WebDriver driver = new RemoteWebDriver(capabilities);
кроме того, исполняемый файл марионетки добавляется в путь (в Windows):
добавление исполняемого файла в путь
селен попробует использовать исполняемый файл в пути. Вам нужно будет добавить его в путь, используя следующее.
наконец, еще один так вопрос где обрабатывается проблема UnreachableBrowserException.
У меня была аналогичная проблема, решенная путем создания переопределенного экземпляра MarionetteDriver с переопределенной реализацией builder. Принятый ответ-более элегантное решение. У меня было много времени, чтобы глубоко в первопричину
public static class CustomBuilder extends org.openqa.selenium.firefox.GeckoDriverService.Builder {
@Override
protected GeckoDriverService createDriverService(File exe, int port, ImmutableList<String> args, ImmutableMap<String, String> environment) {
try {
return new GeckoDriverService(exe, port, args, environment) {
@Override
protected void waitUntilAvailable() throws MalformedURLException {
logger.info("Waiting until avaliable");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
super.waitUntilAvailable();
logger.info("Finished waiting until avaliable");
}
};
} catch (IOException e) {
throw new WebDriverException(e);
}
}
}