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. List<T>排序

    List<Student> studentList = new List<Student>(); Student s = new Student(); s.Name = &qu ...

  2. Android Studio中出现Gradle's dependency cache may be corrupt错误的解决办法

    起因 某次打开AS,提示升级AS,升级后,提示升级gradle,选择升级. 结果在升级gradle时耗时较久,没有耐心,点击停止升级gradle, 还是停在那里,然后关闭AS,还是没反应,启动任务管理 ...

  3. 浅谈stiring数

    在组合数学,Stirling数可指两类数,第一类Stirling数和第二类Stirling数. stirling常应用于许多组合枚举问题中. 第一类stirling数: 对第一类Stirling数   ...

  4. luogu P3916 图的遍历

    P3916 图的遍历 题目描述 给出 N 个点, M 条边的有向图,对于每个点 v ,求 A(v) 表示从点 v 出发,能到达的编号最大的点. 输入输出格式 输入格式: 第1 行,2 个整数 N,MN ...

  5. [LUOGU] P3871 [TJOI2010]中位数

    题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前序列的中位数 中位数是指将一个序列按照从 ...

  6. idea Error:(65, 27) java: 未结束的字符串文字

    今天在使用IDEA的时候,出现了这个错误,原因项目文件编码不一致导致的,解决方法是: 将项目的文件编码全改成一致(UTF-8),如下图所示:

  7. 配置工程文件dll编译后copy路径

    放到工程文件的最后面的配置节点: 下面的配置节点中生成路径换成实际的相对路径就可以了 修改:Prject.csproj 文件里面的配置节点  project配置节点里面的最后面 <Target ...

  8. ssm依赖

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  9. Run-time Settings--General--Run Logic

    LR单用户,重复操作日志 案例:假如你想在一个脚本中,实现登录执行1次,查询执行2次,插入执行3次,怎么办?录3个脚本?每个事务分别在脚本中复制N次? 当然不用,LR早就想到了你的需求,下面让我们隆重 ...

  10. Flask--Config研究

    导入Flask框架后,在项目跟目录下面会有一个Config.py 文件,里面的默认内容为: class Config(object): pass 可以这Config 类里面定义变量和其他对象 如: c ...