An interesting solution to the Ruby Webdriver timeout problem

Source: Internet
Author: User

Rescue in receive

Because when I write Ruby, I feel like I'm dragging it all up, so I prefer to write code in Ruby. Today I encountered a problem with Webdriver timeout, and the problem itself was due to the fact that I had no knowledge of webdriver and broken documents. First, let's simplify the question:


Driver = Selenium::webdriver.for:safari
Driver.navigate.to "Http://www.faraway.com"

wait = selenium::webdriver::wait.new (: timeout = +) # seconds
Wait.until {driver.find_element (: CSS, ' input[name= ' username "])}

Because the site is too far away, the speed is relatively slow, so timeout set a larger value: Timeout = 1000

Here we visit: Faraway This site, and then wait for the input box to enter the user name. The following error message was obtained:

/users/twer/.rvm/gems/[email protected]/gems/selenium-webdriver-2.42.0/lib/ selenium/webdriver/safari/server.rb:41:in' rescue in receive ': Timed off 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 '
from faraway.rb:26: In ' <main> '


The place where I saw the error was called by the place where I wait. I thought I was not set: Timeout = 1000,wait wait time of 1000 seconds, why still not ah?


Monkey patch to save me.

I don't know, there are people blowing on it. Violent settlement. I found the file/selenium/webdriver/safari/server.rb marked in the red section above. (HTTPS://CODE.GOOGLE.COM/P/SELENIUM/SOURCE/BROWSE/RB/LIB/SELENIUM/WEBDRIVER/SAFARI/SERVER.RB)

Found the place where the error occurred 41 lines, is in the receive function:

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


As can be seen, is now >= End_time used to calculate whether to timeout, in front of the end_time is seen by the Time.now + @command_timeout obtained, and then into the begin/rescue/retry. Strange, my: timeout = 1000 Shouldn't it be work?


First Monkey Patch

I copied the above part of the code directly into my source file faraway.rb, made the following changes:

If now >= end_time
Puts @command_timeout
Raise Error::timeouterror, "timed out waiting for Safari to respond"
End

Found that @command_timeout is not 1000, but 60, that is, a minute.


A second monkey patch

Until Msg = @frame. Next
End_time = time.now + 1000
This forces @command_timeout to be set to 1000.


Running like this, no problem.


Explore

Although monkey patch can solve my problem of connecting faraway. However, as a quick test to get feedback is OK, it is still not very pleasant to use. So I began to read the source code, webdriver the code itself is quite simple. It's easy to read, but I don't know what to say. Minutes of discovering the problem is actually here:


Driver = Selenium::webdriver.for:safari,timeout:1000
Driver.navigate.to "Http://www.faraway.com"


The red part is not accounted for in the document, what does the timeout here mean? My wait is not already a timeout, how to driver in the creation of the need?

The reason is that there are two different timeout types. The timeout for wait indicates how long our driver will wait to know if this element appears. And the place where we went wrong is the timeout that driver receives the server's return information. Not sure yet?

In this case, at wait, driver will cycle through the code in the until to see if the situation in until is met. Each time the execution of the driver will send a request, this request actually has timeout time, so we first encountered the problem is not wait itself timeout. Instead, driver sends a command and receives it when it is timeout.

Clearly, it was faraway.com, who wanted to reproduce the problem. Change command timeout to 1 try


If I'm unfortunate again ...

I am the kind of person who is more fortunate than me. But the process of solving the problem is still very happy. Ruby is a dynamic language that can play monkey patches, which is helpful for locating problems quickly and solving problems. Happy.


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.