LoginSignup
31
16

More than 5 years have passed since last update.

Capybara + Selenium WebDriver による E2E テストで Net::ReadTimeout への対応(ヘッドレス Chrome の設定例)

Last updated at Posted at 2018-01-08

Capybara + Selenium WebDriver による E2E テストを実行しているとき Net::ReadTimeout が発生することがある。

Net::ReadTimeout

--- Caused by: ---
IO::EAGAINWaitReadable:
Resource temporarily unavailable - read would block

これへの対応として、

  • (1) タイムアウトをのばす
  • (2) リトライする
  • (3) そもそもタイムアウトに引っ掛かるような処理を見直す

があると思う。(3) については各位がんばりましょうということで、ここでは (1) (2) について書く。

環境

  • Rails 4.2.5(がんばる...)
  • capybara 2.6.2
  • selenium-webdriver 3.8.0
  • Google Chrome 63.0.3239.84
  • ChromeDriver 2.34.522932

タイムアウトをのばす

https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings#internal-timeouts のとおり

client = Selenium::WebDriver::Remote::Http::Default.new
client.read_timeout = 120 # seconds
driver = Selenium::WebDriver.for :remote, http_client: client

みたいなことをやれば良いのだけれど、これをみても、なるほどわからん、という人はいると思うので、もう少し周辺も含めた設定例を書いておく。

ヘッドレス Chrome を使った例

PhantomJS が最新の JS / CSS へ追随しなくなって、E2E テストで使うブラウザーを Chrome へ乗り換えた人も多いと思うので、ヘッドレス Chrome の設定例を書いておく。

# spec/support/capybara.rb

require 'capybara/rails'
require 'capybara/rspec'
require 'selenium-webdriver'

client = Selenium::WebDriver::Remote::Http::Default.new
client.read_timeout = 120 # instead of the default 60

Capybara.register_driver :selenium do |app|
  Capybara::Selenium::Driver.new(
    app,
    browser: :chrome,
    desired_capabilities: Selenium::WebDriver::Remote::Capabilities.chrome(
      chrome_options: {
        args: ['headless', 'window-size=1280,768'],
      },
    ),
    http_client: client,
  )
end

Capybara.javascript_driver = :selenium

ポイント

  • timeout= メソッドは deprecated
    • client.read_timeout = xxx としている箇所、少し古いドキュメントだと client.timeout = xxx と書かれているものもあるけど、timeout= メソッドは deprecated になっている
    • Selenium の Wiki については 先ほど 中の人に直してもらえた(感謝)
  • ヘッドレス Chrome の disable-gpu オプションは不要
  • ヘッドレス Chrome を RSpec + Capybara で使うことについては下記が分かりやすい

リトライする

rspec-retry という便利な Gem があるのでオススメ。

設定例

使い方は公式の README に分かりやすく書いているので特に困らないと思うけれど、参考までに 転職ドラフト で使っている設定を載せておく。

# spec/support/retry.rb

require 'rspec/retry'

RSpec.configure do |config|
  config.verbose_retry = true
  config.display_try_failure_messages = true

  # run retry only on features
  config.around :each, :js do |example|
    # 公式では 3 となっているけれど、日本には三度目の正直という言葉があるし、
    # 3回やってもこけるテストは根本的に対応したほうが良いと考えた
    example.run_with_retry retry: 2
  end

  # callback to be run between retries
  config.retry_callback = proc do |example|
    # run some additional clean up task - can be filtered by example metadata
    Capybara.reset! if example.metadata[:js]
  end
end

ポイント

config.exceptions_to_retry = [Net::ReadTimeout]

とやって、リトライする対象のエラーを指定する方法もある(詳細は公式 README 参照)が、JavaScript を利用した E2E テストは経験上なんやかんやでこけるときがあるので特にエラーを限定しなくて良いのかなと判断した。

31
16
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
16