一个有意思的Ruby Webdriver超时问题的解决过程

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/[email protected]/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/[email protected]/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/safari/server.rb:36:in `receive‘

from /Users/twer/.rvm/gems/[email protected]/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/safari/bridge.rb:68:in `raw_execute‘

from /Users/twer/.rvm/gems/[email protected]/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/remote/bridge.rb:612:in `execute‘

from /Users/twer/.rvm/gems/[email protected]/gems/selenium-webdriver-2.42.0/lib/selenium/webdriver/remote/bridge.rb:110:in `get‘

from /Users/twer/.rvm/gems/[email protected]/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,对于高速定位问题,解决这个问题还是非常有帮助的。开心。

时间: 2025-01-16 08:09:09

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

一个有意思的需求——中文匹配度

引言 最近LZ带头在做一个互联网项目,互联网的东西总是那么新鲜,这也难怪大部分猿友都喜欢互联网.这个互联网项目不仅让LZ开发了一个HBase大数据应用,近期的一次需求讨论会上,又出来一个小需求,蛮有意思的.这些需求在之前枯燥的企业内部应用开发中,还是很难见到的,毕竟内部应用更多的是业务流程的体现. 具体的需求这里不方便透露,但简单的描述一下需求,就是如何判断两个公司名是一个.这其实就是Java当中字符串的相等判断,最简单的当然是用equals来判断.但是由于实际情况是,公司名是由客户手动输出的,

做一个有意思的人

http://www.nowamagic.net/librarys/eight/posts/2545到底应该过一个有意义的人生,还是做一个有意思的人?什么样的人才是一个有意思的人.第一次读这篇文章,我就十分感概.我们从小受教育说要为社会做贡献,上班了被要求以公司为家,或许我们应该思考一下如何做一个有意思的人.这篇文章或许你看过,我觉得可以再看一遍. 作者:黄铁鹰 & 芮成钢 与几位好友们有一个共识:大家对一个人最高的评价是:“这是一个很有意思,很精彩的人”.大家以这个标准,来判断一个人是否值得成

CSAPP中一个有意思的小东西

回家的效率明显下降了,但是第三章还是快要结束的节奏.今天看到定长数组这里的时候,看到一个好玩的东西.在计算机的底层中,所有对数组的操作都是利用指针来完成的.数组其实也是一个很简单的数据结构,就是把一些最简单的数据类型合并在一段连续的内存区域上,这就是一个复合类型---数组. 学C语言的时候,大家都知道访问数组元素有两种方法,一种是利用数组名加索引的形式,另外一种就是利用指针加上偏移量的形式.在底层中,不管你用什么方式来访问元素,最后多会转化成对指针的操作. 在编写 代码的时候,编译器在编译过程中

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

今天阅读了关于Python函数式编程的系列文章,地址在这里: http://www.cnblogs.com/huxi/archive/2011/06/24/2089358.html 里面提到了四个内建迭代函数:reduce.map.filter.zip.其中zip是供同时迭代多个迭代器用的,这里就不讨论了.主要讨论剩下的三个. 我发现一个有意思的事情,就是剩下的三个函数,reduce.map和filter,三者可以相互转换.例如以reduce为基础,可以实现map和filter函数如下: 1 d

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

linux下一个有意思的问题(文件名以短划线开头) 这本是无意中的一个发现. 在linux下,文件名中含有 - 是没有问题,但是如果文件名是以-作为第一个字符的,那么就比较麻烦了. 问题演示 看这里,以短划线开头的文件名似乎对mv cp  rm   等操作免疫了.利用这个特性可以制造出一些比较麻烦的文件或者文件夹来. [email protected]:~$ ls -python.md [email protected]-pc:~$ mv -python.md 5-python.md mv:无效

一个有意思的类扩展 有效解决判空问题

public static class ClassExtensions { public static TResult GetProperty<TClass, TResult>(this TClass obj, Func<TClass, TResult> func) where TClass : class { if ((object) obj == null) return default (TResult); else return func(obj); } public st

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

我最近发现了一个有意思的CSS样式库,和Bootstrap相似,但是它是专门的一个高度可定制的,免费的并且开源的按钮CSS样式库,这里附上它的网址:http://www.bootcss.com/p/buttons/ 接下来介绍怎么使用这个CSS样式库,如上图,进入网址后,点击下载,会出现一个全是代码的网页,然后鼠标右键点击全选,复制,这里的代码就是这个BUTTONS的CSS样式代码, 再接下来就是在你的编辑器中创建一个css文件,然后将所复制的代码全部粘贴上去即可,然后就可以编写你的HTML代码

一个图文混排问题的解决过程

需求如所示:左边的是效果图,右边的是完成后的图                 具体需求描述:用户的回复一条就是一个cell,字数不定.当存在某种条件时,需要在文字(可能换行)的最后一个字后面添加一个能点击的删除按钮小图标,文字支持emoji表情符号. 解决过程: 1.一看到这种文字中需要穿插图片的就想到了富文本中的NSTextAttachment对象,它可以包装一个image后生成一个富文本,再给UILabel显示就能完成显示需求,但是,该对象只能包装UIImage对象,无法监听图片的点击事件

WebClient的超时问题及解决

WebClient的超时问题及解决 转自:http://blog.163.com/[email protected]/blog/static/62440288201112245345838/ Webclient在下载请求时无法设置请求超时时间和请求读写超时时间.WebClient在异步下载时遇到网络不通等问题时没有响应超时造成app挂起. 1.Webclient请求超时设置      重写Webclient的GetWebRequest方法,为HttpWebRequest添加请求超时及读写超时