【问题标题】:Geb/Selenium tests hang loading new pageGeb/Selenium 测试挂起加载新页面
【发布时间】:2015-03-17 19:42:27
【问题描述】:

我的 Selenium 测试经常无限期地挂在 CI 上,总是试图在 driver.get 中加载新页面。我正在使用 PhantomJS 1.9.8。

经过几轮调试,我想我已经将问题追溯到 PhantomJS 中的网页加载未完成。

Selenium RemoteWebDriver 已向 PhantomJS/GhostDriver 发送了一个请求,它正在等待响应。

GhostDriver 仍在接受请求。我可以通过点击curl http://localhost:port/session/:sessionId/url 来查看它停留在哪个页面上,此外,如果我从命令行 (curl -d '{"url": ...}' http://localhost:port/session/:sessionId/url) 重新请求 同一页面,那么被阻止的 Selenium 请求会神奇地从它所在的位置恢复离开了。

更新: Ghostdriver 本身并没有挂起——不过,它的默认超时基本上是无限的。如果我指定页面加载超时,例如manage().timeouts().pageLoadTimeout(60, TimeUnit.SECONDS),那么当 PhantomJS 中发生问题时,GhostDriver 将返回超时错误响应,测试将失败,然后构建将继续。

如果我调试 PhantomJS 本身 (--debug=TRUE),那么我认为这是故障点日志中的最后一件事

2015-03-21T21:26:39 [DEBUG] WebPage - updateLoadingProgress: 86 (然后在超时之前什么都没有)

Java 端的堆栈跟踪在挂起点是这样的:

"Forwarding get on session fd1ac2c0-ccd4-11e4-a596-a1f7b09caa5d to remote" prio=10 tid=0x0000000001f74800 nid=0x5cc3 runnable [0x00002b87c3039000]
 java.lang.Thread.State: RUNNABLE
     at java.net.SocketInputStream.socketRead0(Native Method)
     at java.net.SocketInputStream.read(SocketInputStream.java:150)
     at java.net.SocketInputStream.read(SocketInputStream.java:121)
     at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:166)
     at org.apache.http.impl.io.SocketInputBuffer.fillBuffer(SocketInputBuffer.java:90)
     at horg.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:281)
     at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:92)
     at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:62)
     at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:254)
     at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:289)
     at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:252)
     at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:219)
     at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:300)
     at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:127)
     at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:712)
     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:517)
     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
     at org.openqa.selenium.remote.HttpCommandExecutor.fallBackExecute(HttpCommandExecutor.java:316)
     at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:295)
     at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:66)
     at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:527)
     at org.openqa.selenium.remote.RemoteWebDriver.get(RemoteWebDriver.java:276)
     at org.openqa.selenium.WebDriver$get.call(Unknown Source)
     at geb.Browser.go(Browser.groovy:371)
     at geb.Browser$go.call(Unknown Source)
     at geb.Page.to(Page.groovy:169)

感觉与此类似,但使用的是 PhantomJS 而不是 Firefox:

Firefox WebDriver hangs waiting for page to load

【问题讨论】:

  • 尝试使用 PhantomJS 2。
  • 在有 Linux 二进制文件之前不是一个选项,或者有人告诉我如何可移植/静态编译它 - 我可以从源代码编译但需要在其他地方编译它,而不是在我的 CI 盒上。

标签: selenium phantomjs geb ghostdriver


【解决方案1】:

我希望你能找到一种方法在你的代码中实现这一点,但是当我遇到与 PhantomJS 挂起类似的情况时,这对我有用。

我追踪到它挂在 driver.get() 调用上,对我来说这意味着某些事情没有通过,或者网络驱动程序只是没有 - 出于某种原因 - 加载成功命令返回驱动程序,允许脚本继续。

所以,我添加了以下内容:

driver = webdriver.PhantomJS()

# set timeout information
driver.set_page_load_timeout(15)

我在 5 秒(秒)的时间内对此进行了测试,但它等待的时间不够长,什么都不会发生。 15 秒对我来说效果很好,但这也许是你应该测试的。

除此之外,每当有 webdriver 超时选项时,我还创建了一个循环,以便driver.get() 可以尝试重新发送.get() 命令。实现try / except 堆叠场景,我能够解决这个问题:

while finished == 0:
    try:
        driver.get(url3)
        finished = 1
    except:
        sleep(5)

我见过一个例外句柄:

except TimeoutException as e:
    #Handle your exception here
    print(e)

但我没有用这个。不过,知道如何捕获特定异常可能会很好。

有关超时的更多选项,请参阅此解决方案:Setting timeout on selenium webdriver.PhantomJS

【讨论】:

    猜你喜欢
    • 2014-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 2011-10-18
    • 2014-05-20
    • 1970-01-01
    相关资源
    最近更新 更多