Performance Plus Oil

Performance Plus Oil

Commercial Contractors

Commercial Contractors

Marushka Handprints

Marushka Handprints

CDCookie

CDCookie

Wheatley-Gaso

Wheatley-Gaso

D.R. Gillcrest

D.R. Gillcrest

Fixing Selenium Timeout::Error

Created by Torey Heinz on September 27, 2011

While running our cucumber test suite, sometimes Firefox would hang and raise a Timeout::Error with this backtrace:

When I go to the home page
      execution expired (Timeout::Error)
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/timeout.rb:64:in `rbuf_fill'
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/net/protocol.rb:134:in `rbuf_fill'
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/net/protocol.rb:116:in `readuntil'
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/net/protocol.rb:126:in `readline'
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/net/http.rb:2028:in `read_status_line'
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/net/http.rb:2017:in `read_new'
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/net/http.rb:1051:in `request'
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/net/http.rb:1037:in `request'
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/net/http.rb:543:in `start'
      /Users/brian/.rvm/rubies/ruby-1.8.7-p352/lib/ruby/1.8/net/http.rb:1035:in `request'
      ./features/step_definitions/web_steps.rb:24:in `/^(?:|I )go to (.+)$/'

Sometimes the tests would fail simply when going to a page, as above. Other times they would fail on a large file upload. Curiously, we’d get only get this timeout error while running the full test suite.

The Timeout::Error was especially frustrating because it would then appear after every scenario. It continued to be raised when Capybara tries to reset each of its sessions.

We still haven’t gotten to the root of the problem. Clearly, Firefox has hung or the connection between it and the webdriver server have been lost. In the mean time, we’ve worked out some stopgaps.

If it appears that selenium-webdriver isn’t giving Firefox enough time to complete the request, you can set the timeout duration by adding the following code to features/env.rb:

Capybara.register_driver :selenium do |app|
  http_client = Selenium::WebDriver::Remote::Http::Default.new
  http_client.timeout = 100
  Capybara::Selenium::Driver.new(app, :browser => :firefox, :http_client => http_client)
end

If more time doesn’t prevent the problem, you can at least prevent the Timeout::Error from breaking all the other tests. Add the following to features/env.rb:

After("@selenium") do |scenario|
  if scenario.exception.is_a? Timeout::Error
    # restart Selenium driver
    Capybara.send(:session_pool).delete_if { |key, value| key =~ /selenium/i }
  end
end

If any Selenium scenarios raises a Timeout::Error, the above code will cause Capybara to forget about the Selenium session and won’t try to reset it at the end of every test. If Cucumber runs across another Selenium test, Capybara will fire up a new browser.

Let us know if you discover a solution to the problem.

  1. Justin Justin — October 10, 2011

    I run into this all the time! Please let me know if you find the cause…

What are your thoughts?