rescue in receive

由于写ruby的时候感觉混身上下都拽起来了,所以比較喜欢用ruby写代码。

今天遇到了一个webdriver timeout的问题,问题本身还是由于我对webdriver不了解以及破文档导致的。首先我们把问题简化一下:

driver = Selenium::WebDriver.for :safari

driver.navigate.to "http://www.faraway.com"

wait = Selenium::WebDriver::Wait.new(:timeout => 1000) # seconds

wait.until { driver.find_element(:css, 'input[name="username"]') }

由于考虑到站点太远了,速度比較慢,于是timeout设的值比較大:timeout => 1000

这里我们訪问:faraway这个站点,然后等待出现输入框输入username。

得到了例如以下错误信息:

/Users/twer/.rvm/gems/ruby-2.1.1@global/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/safari/server.rb:41:in`rescue
in receive': timed out waiting for Safari to respond (Selenium::WebDriver::Error::TimeOutError)


from /Users/twer/.rvm/gems/ruby-2.1.1@global/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/safari/server.rb:36:in `receive'

from /Users/twer/.rvm/gems/ruby-2.1.1@global/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/safari/bridge.rb:68:in `raw_execute'

from /Users/twer/.rvm/gems/ruby-2.1.1@global/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/remote/bridge.rb:612:in `execute'

from /Users/twer/.rvm/gems/ruby-2.1.1@global/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/remote/bridge.rb:110:in `get'

from /Users/twer/.rvm/gems/ruby-2.1.1@global/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/common/navigation.rb:14:in `to'

fromfaraway.rb:26:in `<main>'

看了出错的地方就是我wait的地方调用的。我心想我这不是设了:timeout => 1000。wait的等待时间为1000秒吗,怎么还搞不定啊?

Monkey Patch来解救我了

搞不定啊,上面有人在吹啊,咋办嘛。暴力解决。

我找到了上面红色部分标明的文件/selenium/webdriver/safari/server.rb。(https://code.google.com/p/selenium/source/browse/rb/lib/selenium/webdriver/safari/server.rb

找到了出错的地方41行,是在receive函数里:

def receive

   @frame ||= WebSocket::Frame::Incoming::Server.new(:version => @version)

   until msg = @frame.next

end_time = Time.now + @command_timeout



   begin

      data = @ws.read_nonblock(1)

      rescue Errno::EWOULDBLOCK, Errno::EAGAIN

         now = Time.now

         if now >= end_time

            raise Error::TimeOutError, "timed out waiting for Safari to respond"   #第41行

         end



         IO.select([@ws], nil, nil, end_time - now)

         retry

      end



      @frame << data

   end



   puts "<<< #{msg}" if $DEBUG



   WebDriver.json_load msg.to_s

end





能够看出,是now >= end_time用来计算是否超时。在看前面end_time是由Time.now + @command_timeout得到的,然后进入begin/rescue/retry的。奇怪,我的:timeout => 1000不应该是work的吗?

第一个monkey patch

我把上面那部分代码直接拷到了我的源文件faraway.rb中,做了例如以下改动:

if now >= end_time

   puts @command_timeout

   raise Error::TimeOutError, "timed out waiting for Safari to respond"

end

发现@command_timeout不是1000。而是60,也就是一分钟

第二个monkey patch

until msg = @frame.next

   end_time = Time.now + 1000

这样强制让@command_timeout设为1000

这样执行,没有问题了

探个到底

尽管monkey patch能够解决我连接faraway的问题。可是,作为高速试验得到反馈还行。真这样用还是不太愉快。

于是我就開始读源码,webdriver本身的代码还是挺简单的。非常easy看懂。详细怎么看我就不讲了。分分钟发现了问题事实上是在这里:

driver = Selenium::WebDriver.for :safari,
timeout: 1000

driver.navigate.to "http://www.faraway.com"

红色的部分在文档上是没有交代的,那这里的timeout是什么意思呢?我的wait不是已经有timeout了吗。怎么在Driver的创建时还须要呢?

原因是这是两种不同的timeout。wait的timeout表示的是。我们的driver会等待多久知道这个元素出现。而我们出错的地方是driver接收server返回信息的timeout。

还不清楚?

这样说,在wait的时候,driver会周期轮询的去运行until中的代码。看看until中的情况是否得到了满足。

每次运行的时候Driver对会发一个请求。这个请求事实上也是有timeout时间的。所以我们最開始遇到的问题并非wait本身timeout了。

而是driver发送命令后接收的时候timeout了。

明了了吧,都是faraway.com搞得怪,想重现这个问题。把command timeout改为1试试

假设我再次不幸。。

我一仅仅搅得自己是运气比較背的那种人。

只是解决这个问题的过程还是非常开心。ruby这样的动态语言,能够打monkey patch,对于高速定位问题,解决这个问题还是非常有帮助的。开心。

一个有意思的Ruby Webdriver超时问题的解决过程的更多相关文章

  1. linux下一个有意思的问题(文件名以短划线或空格开头)

    linux下一个有意思的问题(文件名以短划线开头) 这本是无意中的一个发现. 在linux下,文件名中含有 - 是没有问题,但是如果文件名是以-作为第一个字符的,那么就比较麻烦了. 问题演示 看这里, ...

  2. Ruby学习笔记2 : 一个简单的Ruby网站,搭建ruby环境

    Ruby on Rails website 的基础是 请求-返回 循环. 首先是浏览器请求服务器, 第二步,Second, in our Rails application, the route ta ...

  3. 一个有意思的CSS样式库--BUTTONS

    我最近发现了一个有意思的CSS样式库,和Bootstrap相似,但是它是专门的一个高度可定制的,免费的并且开源的按钮CSS样式库,这里附上它的网址:http://www.bootcss.com/p/b ...

  4. Python一个有意思的地方:reduce、map、filter

    今天阅读了关于Python函数式编程的系列文章,地址在这里: http://www.cnblogs.com/huxi/archive/2011/06/24/2089358.html 里面提到了四个内建 ...

  5. 网易笔试题:浏览器中输入一个url后回车到返回页面信息的过程

    You enter a URL into the browser输入一个url地址 The browser looks up the IP address for the domain name浏览器 ...

  6. 这几天帮一个朋友解决了一点小问题(RF的有些小问题及解决过程)

    最近涉猎自动化太少了,以至于都不经常更新了.最近一个朋友在做移动端自动化的时候遇到了一些小问题来找我解决.本人也不是很精通,只是接触的时间长了一点了.下面就是一些问题和解决过程: 1.她刚过来的时候, ...

  7. ecshop运行超过30秒超时的限制解决办法

    ecshop运行超过30秒超时的限制解决办法 ECSHOP模板/ecshop开发中心(www.68ecshop.com) / 2014-06-04 ecshop运行超过服务器默认的设置30秒的限制时会 ...

  8. WebClient的超时问题及解决

    WebClient的超时问题及解决 转自:http://blog.163.com/xiaozhi797@126/blog/static/62440288201112245345838/   Webcl ...

  9. pip 安装出现超时问题的解决

    pip 安装出现超时问题的解决 我们在用默认的pip源进行安装python库时,会出现超时问题下载不了,如下图显示所示: 那么我们应该如何解决呢? 方法: 在自己电脑的  C:\Users\yanji ...

随机推荐

  1. selenium Select下拉框

    先来认识一下下拉框,以百度的“高级设置”为例 介绍两种方法来处理下拉框:使用click事件,使用Select方法 使用click事件 上述下拉框的源代码如下: 虽然我们可以在html源文件中看到sel ...

  2. nginx 集群

    Nginx是什么? Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器.一直纳闷这个X是怎么来 ...

  3. Linux启动流程CentOS6和7的区别

    目 录 Linux启动流程    I 第1章 CentOS6启动流程    1 1.1 BIOS    1 1.2 MBR    1 1.3 GRUB    1 1.4 kernel(加载内核)    ...

  4. PHP fpm配置和优化

    pm.max_children = 1024 #最大子进程数 maximum number of child processes when pm is set to 'dynamic' or 'ond ...

  5. msp430入门编程30

    msp430中C语言的文件管理

  6. vagrant的学习 之 Yii2

    vagrant的学习 之 Yii2 本文根据慕课网的视频教程练习,感谢慕课网! 慕课视频学习地址:https://www.imooc.com/video/14218. 慕课的参考文档地址:https: ...

  7. FusionCharts for Flex 如何更改图表数据

    FusionCharts allows to change chart data and re-render the chart, after it has loaded on the user’s ...

  8. Jquery操作事件

    1.文档加载事件 2.DOM单击双击事件 3.DOM获得焦点,失去焦点问题 4.DOM鼠标移入,移出事件 <!DOCTYPE html> <html> <head> ...

  9. Populating Next Right Pointers in Each Node (DFS,没想到)

    Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *nex ...

  10. Codeforces 920G(二分+容斥)

    题意: 定义F(x,p)表示的是一个数列{y},其中gcd(y,p)=1且y>x 给出x,p,k,求出F(x,p)的第k项 x,p,k<=10^6 分析: 很容易想到先二分,再做差 然后问 ...