一个有意思的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/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超时问题的解决过程的更多相关文章
- linux下一个有意思的问题(文件名以短划线或空格开头)
linux下一个有意思的问题(文件名以短划线开头) 这本是无意中的一个发现. 在linux下,文件名中含有 - 是没有问题,但是如果文件名是以-作为第一个字符的,那么就比较麻烦了. 问题演示 看这里, ...
- Ruby学习笔记2 : 一个简单的Ruby网站,搭建ruby环境
Ruby on Rails website 的基础是 请求-返回 循环. 首先是浏览器请求服务器, 第二步,Second, in our Rails application, the route ta ...
- 一个有意思的CSS样式库--BUTTONS
我最近发现了一个有意思的CSS样式库,和Bootstrap相似,但是它是专门的一个高度可定制的,免费的并且开源的按钮CSS样式库,这里附上它的网址:http://www.bootcss.com/p/b ...
- Python一个有意思的地方:reduce、map、filter
今天阅读了关于Python函数式编程的系列文章,地址在这里: http://www.cnblogs.com/huxi/archive/2011/06/24/2089358.html 里面提到了四个内建 ...
- 网易笔试题:浏览器中输入一个url后回车到返回页面信息的过程
You enter a URL into the browser输入一个url地址 The browser looks up the IP address for the domain name浏览器 ...
- 这几天帮一个朋友解决了一点小问题(RF的有些小问题及解决过程)
最近涉猎自动化太少了,以至于都不经常更新了.最近一个朋友在做移动端自动化的时候遇到了一些小问题来找我解决.本人也不是很精通,只是接触的时间长了一点了.下面就是一些问题和解决过程: 1.她刚过来的时候, ...
- ecshop运行超过30秒超时的限制解决办法
ecshop运行超过30秒超时的限制解决办法 ECSHOP模板/ecshop开发中心(www.68ecshop.com) / 2014-06-04 ecshop运行超过服务器默认的设置30秒的限制时会 ...
- WebClient的超时问题及解决
WebClient的超时问题及解决 转自:http://blog.163.com/xiaozhi797@126/blog/static/62440288201112245345838/ Webcl ...
- pip 安装出现超时问题的解决
pip 安装出现超时问题的解决 我们在用默认的pip源进行安装python库时,会出现超时问题下载不了,如下图显示所示: 那么我们应该如何解决呢? 方法: 在自己电脑的 C:\Users\yanji ...
随机推荐
- 漫谈Word2vec之skip-gram模型
https://zhuanlan.zhihu.com/p/30302498 陈运文 复旦大学 计算机应用技术博士 40 人赞同了该文章 [作者] 刘书龙,现任达观数据技术部工程师,兴趣方向主要为自 ...
- Visual Studio 安装VS10x CodeMAP
最近出差,用的是公司电脑,电脑安装的是Visual Studio 2017 VS10x CodeMap 支持Visual Studio 2010, 2012, 2013, 2015,不支持Visual ...
- [LOJ] 分块九题 2
https://loj.ac/problem/6278 区间修改,查询区间第k大. 块内有序(另存),块内二分. 还是用vector吧,数组拷贝排序,下标搞不来.. //Stay foolish,st ...
- spring-mvc jackson配置json为空不输出
使用的spring-mvc版本是4.1.6,jackson版本是2.1.4 在spring-mvc配置文件中添加以下代码就行 <mvc:annotation-driven> <mvc ...
- 关于flock文件锁的阻塞与非阻塞
阻塞模式,程序会一直等待. <?php $fp = fopen("lock.txt", "r"); if(flock($fp,LOCK_EX)) { // ...
- 关于Python中包裹传参和解包裹的理解
1.包裹传参 首先思考一个问题:为什么要有包裹传参?原因包括但不仅限于以下两点:①不确定参数的个数.②希望函数定义的更加松散灵活 包裹传参分两种:包裹位置传参和包裹关键字传参.先看包裹位置传参: 在这 ...
- python编程之API入门: (二)python3中使用新浪微博API
回顾API使用的流程 通过百度地图API的使用,我理解API调用的一般流程为:生成API规定格式的url->通过urllib读取url中数据->对json格式的数据进行解析.下一步,开始研 ...
- C# 中的新增功能
百度搜索:C# 中的新增功能 微软有站点专门介绍:C# 中的新增功能. 地址:https://docs.microsoft.com/zh-cn/dotnet/csharp/whats-new/inde ...
- poj 1780 , poj 1392 欧拉回路求前后相互衔接的数字串
两道题目意思差不多 第一题是10进制 , 第二题是2进制的 都是利用欧拉回路的fleury算法来解决 因为我总是希望小的排在前面,所以我总是先将较小数加入栈,再利用另一个数组接收答案,但是这里再从栈中 ...
- HDU1686 计算模式串匹配的次数
题目大意: 输入一个T,表示有T组测试数据: 每组测试数据包括一个字符串W,T,T长度大于W小于1000000,w长度小于10000,计算W匹配到T中成功的次数: 这题很明显要用KMP算法,不然很容易 ...