2015-12-29 8 views
9

Attualmente sto giocando con il Selenium Marionette WebDriver. Nella mia applicazione, voglio aprire più driver Marionette in sequenza. Fondamentalmente qualcosa di simile:Selenium Marionette driver UnreachableBrowserException al secondo avvio

MarionetteDriver driver = new MarionetteDriver(); 
// do some stuff 
driver.quit(); 

// a while later 

driver = new MarionetteDriver(); 
// do some stuff 
driver.quit(); 

Ora sto affrontando il problema, che solo la prima istanza burattino può essere avviato con successo e per ogni tentativo tardi, sto ricevendo la seguente eccezione. Il problema si verifica ogni volta e la porta utilizzata cambia sempre, quindi non c'è ovviamente alcun conflitto di porta.

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 

Qualsiasi suggerimento apprezzato!

risposta

8

Dopo aver scavato un po 'più in profondità, sono venuto alle seguenti conclusioni che alla fine ha risolto il mio problema:

  1. Marionette resp. wires utilizza due porte (vedere wires --help); un marionette-port e un 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 
    

    l'esecuzione di più MarionetteDrivers simultaneamente entrambe le porte devono essere diverso da l'istanza già in esecuzione ovviamente. Tuttavia, quando si utilizza il costruttore predefinito new MarionetteDriver(), lo marionette-port rimane costante (e non viene determinato in base ad alcuna porta libera). Abbiamo usato qualche soluzione (vedi sotto) per lo GeckoDriverService.Builder per scegliere sempre due porte disponibili scelte a caso.

  2. La corrente (versione 2.48.2) GeckoDriverService ha un'implementazione vuota di waitUntilAvailable() (che va a controllare, se il WebDriver è pronto ad andare). Sporadicamente, questo ha portato allo UnreachableBrowserException pubblicato sopra.

per aggirare questi problemi, abbiamo fatto qualcosa di simile a questo alla fine:

// 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

Vorrei sollevare la richiesta di pull, ho trascorso quasi 2 ore, cercando di risolvere lo stesso problema. – Anton

0

Principalmente UnreachableBrowserException accade quando Selenium non è riuscito a trovare l'exe richiesto del driver. Poiché non hai impostato le funzionalità del driver, suppongo che i seguenti passaggi risolveranno il tuo problema.

Secondo Mozilla NDP link Marionette è impostato come 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); 

Inoltre, Marionetta eseguibile viene aggiunto al percorso (in Windows):

Aggiungendo l'eseguibile al PATH

Selenium proverà a utilizzare l'eseguibile nel percorso. Dovrai aggiungerlo al percorso usando quanto segue.

Infine, un altro SO question in cui viene gestito un problema UnreachableBrowserException.

+1

Grazie per il suggerimento. Tuttavia, il problema non è correlato al PATH; come ho affermato, la prima istanziazione di 'MarionetteDriver' funziona correttamente e il problema si verifica solo nei tentativi successivi. Ho anche provato a utilizzare un 'RemoteWebDriver', ma questo non aiuta neanche. – qqilihq

2

è necessario gestire il binario previsto dalla Marionette. Puoi farlo a mano (scarica il file binario da solo ed esporta la variabile corretta), oppure puoi farlo automaticamente usando WebDriverManager.Basta aggiungere la seguente dipendenza:

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

E poi, nella chiamata codice per:

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

Anche se sembra un'estensione molto utile, non sono sicuro di come risolva il problema dato. Potrebbe essere che potresti elaborare? – qqilihq

+0

Questa estensione non richiede la configurazione di MarionetteDriver sul nostro computer locale. Per me funziona. – SkorpEN

0

ho avuto problema simile, risolto con la creazione di un'istanza di override MarionetteDriver con l'attuazione costruttore sovrascritto. La risposta accettata è tuttavia una soluzione più elegante. Ho avuto molto tempo per approfondire la causa principale

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); 
     } 
    } 
} 
Problemi correlati