2015-12-29 3 views
9

Я сейчас играю с Selenium Marionette WebDriver. В моем приложении я хочу последовательно открыть несколько драйверов Marionette. В основном что-то вроде этого:Selenium Marionette driver UnreachableBrowserException при втором запуске

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 

Любые указатели оценили!

ответ

8

После копать немного глубже, я пришел к следующим выводам, которые в конечном итоге решить мою проблему:

  1. марионеток соотв. wires использует два порта (см. wires --help); marionette-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. Текущая (версия 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); 
+0

Я бы поднял тянущий запрос, я потратил почти 2 часа, пытаясь решить ту же проблему. – Anton

0

В основном UnreachableBrowserException происходит, когда Selenium не смог найти требуемый exe драйвера. Поскольку вы не установили возможности драйвера, я предполагаю, что следующие шаги помогут решить вашу проблему.

В соответствии с Mozilla MDN link Marionette устанавливается как 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):

Добавление исполняемого файла в PATH

Selenium попытается использовать исполняемый файл в пути. Вам нужно будет добавить его в путь, используя следующее.

И наконец, еще один SO question, в котором обрабатывается проблема UnreachableBrowserException.

+1

Благодарим за предложение. Однако проблема не связана с PATH; как я уже сказал, первое создание «MarionetteDriver» отлично работает, и проблема возникает только при последующих попытках. Я также попытался использовать «RemoteWebDriver», но это тоже не помогает. – qqilihq

2

Вы должны обрабатывать двоичный файл требуемого марионеток. Вы можете сделать это вручную (загрузите двоичный файл самостоятельно и экспортируйте соответствующую переменную), или вы можете сделать это автоматически, используя WebDriverManager.Просто добавьте следующую зависимость:

<dependency> 
    <groupId>io.github.bonigarcia</groupId> 
    <artifactId>webdrivermanager</artifactId> 
    <version>1.6.0</version> 
</dependency> 

, а затем в вашем коде вызова:

FirefoxDriverManager.getInstance().setup(); 
+1

Хотя это звучит как очень полезное расширение, я не уверен, как он решает данную проблему. Может быть, вы могли бы разработать? – qqilihq

+0

Это расширение требует хлопот по настройке MarionetteDriver на нашей локальной машине. Для меня это работает. – SkorpEN

0

У меня был подобный вопрос, решен путем создания перекрытого экземпляра MarionetteDriver с перегруженной реализацией строителя. Однако принятый ответ - более изящное решение. Было много времени, чтобы глубоко в корень причины

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); 
     } 
    } 
} 
Смежные вопросы