0

これは私のコードのバグですか、それとも Selenium や RSpec などのバグですか?

私が書いている Cucumber テストでは、Chrome ドライバーをシャットダウンして再起動する必要があります。ただし、この 2 番目のドライバーを適切にシャットダウンすることはできません。以下の簡略化された例は、問題を示しています: (以下のコードは、Cucumber の複雑さを追加せずに問題を示しているため、RSpec のみです。)

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

このコードを実行すると、次のエラーが発生します。

/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'

ブロックが実行されると、2 番目の chromedriver プロセスが実行されなくなっていることがわかりますat_exit。これは、シャットダウンの原因となっているメカニズムが何であれ、Chrome ウィンドウを開いたままにするため、問題を引き起こします。

RSpec のafter(:suite)メカニズムは期待どおりに機能します。Cucumber に対応するメカニズムはありますか (この場合は機能しない 以外at_exit)? または、ブロックが実行される前に chomedriver が終了しないようにする方法はありますか (そのため、期待どおりにメソッドをat_exit使用してシャットダウンできます)。quit

最新の Selenium および rspec パッケージを使用して、Mac OS 10.9.5 で Ruby 2.0.0 を実行しています。

4

1 に答える 1

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

于 2015-07-07T19:35:03.420 に答える