0

Is this a bug in my code, or a bug in Selenium, RSpec, etc.?

The Cucumber tests I'm writing need to shut down and re-launch the Chrome driver. However, I can't get this second driver to shut down properly. The stripped-down example below shows the problem: (The code below is RSpec only because it demonstrates the issue without adding the complexity of Cucumber.)

require 'selenium-webdriver'

RSpec.configure do |config|
       config.before(:suite) do
           $driver = Selenium::WebDriver.for :chrome
         end
     end

describe "A potential rspec/selenium/chrome driver bug" do 
  it "doesn't play nice with at_exit" do    
    # quit the initial driver and start a new one.
    $driver.quit
    $driver = Selenium::WebDriver.for :chrome    
  end # it
end # end describe

at_exit do
  $driver.quit
end

When I run this code I get the following error:

/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:878:in `initialize': Connection refused - connect(2) (Errno::ECONNREFUSED)
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:878:in `open'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:878:in `block in connect'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/timeout.rb:52:in `timeout'

I can tell that the second chromedriver process no longer running when the at_exit block runs. This causes a problem because whatever mechanism is causing the shutdown is leaving the Chrome window open.

RSpec's after(:suite) mechanism works as expected. Is there a corresponding mechanism for Cucumber (other than at_exit, which isn't working in this case)? Or, is there a way to prevent chomedriver from exiting before the at_exit block runs (so I can shut it down using the quit method as expected)?

I'm running Ruby 2.0.0 on Mac OS 10.9.5 using the latest selenium and rspec packages.

Zack
  • 6,232
  • 8
  • 38
  • 68
  • The code runs as expected with the Safari and Firefox drivers. I get the same error running this code with the Chrome driver in CentOS Linux. – Zack Jul 06 '15 at 14:18

1 Answers1

2

The problem is a bug in my code. The driver needs to be created before env.rb defines its own at_exit hook. Here's why:

A typical env.rb for cucumber looks like this:

$driver = Selenium::WebDriver.for :chrome, :switches => %w[--disable-cache --ignore-certificate-errors]

at_exit do
  $driver.quit
end

The code that creates the driver object (Selenium::WebDriver.for :chrome) also registers an at_exit hook that shuts down the chromedriver process.

at_exit hooks run in the opposite order they were created. Therefore, a typical execution of cucumber looks like this:

  1. env.rb creates a new driver
  2. Driver defines at_exit hook to quit itself
  3. env.rb defines at_exit hook to quit driver
  4. Cucumber features run
  5. at_exit hook from env.rb is called
  6. Driver's at_exit hook is called

In my case, I created a driver inside a cucumber feature, which caused the driver's at_exit hook to be defined after the at_exit hook in env.rb. As a result, the driver's at_exit hook runs first, causing the call to $driver.quit in env.rb to fail.

The best solution in this case is to create a second driver when necessary and destroy that second driver at the end of the scenario (as opposed to replacing the primary driver with a new one).

Thanks to Alex Rodionov for pointing out my mistakes. https://github.com/SeleniumHQ/selenium/issues/742

Zack
  • 6,232
  • 8
  • 38
  • 68