问题描述
我目前正在与Selenium Marionette WebDriver
玩耍.在我的应用程序中,我想顺序打开多个Marionette驱动程序.基本上是这样的:
I'm currently playing around with the Selenium Marionette WebDriver
. In my application, I want to open multiple Marionette drivers sequentially. Basically something like this:
MarionetteDriver driver = new MarionetteDriver();
// do some stuff
driver.quit();
// a while later
driver = new MarionetteDriver();
// do some stuff
driver.quit();
现在,我面临的问题是,只有第一个Marionette实例可以成功启动,对于以后的每次尝试,我都会遇到以下异常.问题每次都会发生,并且使用的端口总是在变化,因此显然没有端口冲突.
Now I'm facing the problem, that only the first Marionette instance can be successfully started and for each later attempt, I'm getting the following exception. The problem happens every time and the used port always changes, so there is obviously no port conflict.
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
任何指针表示赞赏!
推荐答案
深入研究之后,我发现了以下发现,这些发现最终解决了我的问题:
After digging a little deeper, I came to the following findings which eventually solved my issue:
-
牵线木偶
wires
使用两个端口(请参见wires --help
);marionette-port
和webdriver-port
:
Marionette resp.
wires
uses two ports (seewires --help
); amarionette-port
and awebdriver-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
使用了一些变通方法(请参阅下文),以始终选择两个随机选择的可用端口.
When running multiple MarionetteDrivers
simultaneously, both ports have to be different from the already running instance obviously. However, when using the default constructor new MarionetteDriver()
the marionette-port
remains constant (and is not determined based on some free port). We used some workaround (see below) for the GeckoDriverService.Builder
to always pick two randomly-chosen available ports.
当前(版本2.48.2)GeckoDriverService
具有waitUntilAvailable()
的空实现(应检查WebDriver
是否准备就绪).有时,这导致上面发布的UnreachableBrowserException
.
The current (version 2.48.2) GeckoDriverService
has an empty implementation of waitUntilAvailable()
(which should check, if the WebDriver
is ready to go). Sporadically, this lead to the UnreachableBrowserException
posted above.
为避免这些问题,我们在最后做了这样的事情:
To circumvent these issues, we did something like this at the end:
// 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);
这篇关于Selenium Marionette驱动程序第二次启动时出现UnreachableBrowserException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!