Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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 テストは経験上なんやかんやでこけるときがあるので特にエラーを限定しなくて良いのかなと判断した。

inouetakuya
STORES / hey ではたらくフロントエンドエンジニア。Nuxt.js、Vuex、Vue.js 公式ドキュメントの翻訳者、メンテナ。良い UI をつくりたいと日々思っています
https://blog.inouetakuya.info/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした