テスト用のCIサービスにHeroku CIを使ったところ、systemテストでNet::ReadTimeout
が頻発しました。
driven_byメソッドにoptionsオプションを加え、timeout: 秒数
を指定したところ治りました。
rails_helper.rb
config.before(:each) do |example|
if example.metadata[:type] == :system
driven_by :selenium, using: :headless_chrome, screen_size: [2000, 3000],
options: { timeout: 120 }
end
end
以下、各種ライブラリのソースコードから。driven_byメソッドのoptionsオプションは、Capybara::Selenium::Driver に渡されます。
actionpack-6.1.4.4/lib/action_dispatch/system_testing/driver.rb
def browser_options
@options.merge(options: @browser.options).compact
end
def register_selenium(app)
Capybara::Selenium::Driver.new(app, **{ browser: @browser.type }.merge(browser_options)).tap do |driver|
driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size)
end
end
Capybaraでは、options[:timeout] は read_timeout の値として、Capybara::Selenium::PersistentClient(Selenium::WebDriver::Remote::Http::Defaultのサブクラス)に渡されます。
capybara-3.36.0/lib/capybara/selenium/driver.rb
if options[:timeout]
::Capybara::Selenium::PersistentClient.new(read_timeout: options[:timeout])
else
::Capybara::Selenium::PersistentClient.new
end
Seleniumでは、read_timeout の値は、Net::HTTPのインスタンス(下のコードのhttp)に渡されます。
selenium-webdriver-4.1.0/lib/selenium/webdriver/remote/http/default.rb
def initialize(open_timeout: nil, read_timeout: nil)
@open_timeout = open_timeout
@read_timeout = read_timeout
super()
end
# 略
def http
@http ||= begin
http = new_http_client
if server_url.scheme == 'https'
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
http.open_timeout = open_timeout if open_timeout
http.read_timeout = read_timeout if read_timeout
start(http)
http
end
end
ということで、driven_byメソッドのoptionsオプションに指定したtimeoutの値は、最終的に Net::HTTPのread_timeoutの値(デフォルトは60) となります。