Capybara/Selenium 在 location.reload() 上随机得到一个 Net::ReadTimeout
Capybara/Selenium gets a Net::ReadTimeout randomly on location.reload()
我正在使用 Capybara、selenium-webdriver gem 和 chromedriver 来驱动我的 javascript 启用测试。
问题是我们大约 50% 的构建由于 Net::ReadTimeout
错误而失败。起初这表现为 'could not find element' 错误,但在我将 Capybara 的默认最长等待时间提高到 30 秒后,我开始看到超时。
我检查了超时发生时的屏幕截图,它停留在我们在使用 Javascript 函数 location.reload()
重新加载页面之前简要显示的 'Successfully logged in' 模态。
我在本地 运行 进行了测试,有时可以重现,也 运行domly。有时它会通过此模式压缩并重新加载如此之快你几乎看不到它,而其他时候它会永远挂起。
我觉得这不是资产编译问题,因为此时网站已经加载,以便用户访问登录表单。
想知道是否有人以前见过此问题并知道解决方案。
具体代码:
visit login_path
page.within '#sign-in-pane__body' do
fill_in 'Email', with: user.email
click_button 'Submit'
end
expect(page).to have_content 'Enter Password'
page.within '#sign-in-pane__body' do
fill_in 'Password', with: user.password
click_button 'Submit'
end
expect(page).to have_text 'Home page landing text'
挂断发生在 click_button 'Submit'
和等待主页文本之间。
导致超时的逻辑流程是用户提交登录表单,我们等待服务器呈现一个 .js.erb
模板,该模板在成功登录后触发 JS 事件。当触发发生时,我们会显示一个模式,说明登录成功,然后执行 location.reload()
.
事实证明,这并不是在 JS 中执行 location.reload()
所独有的。有时只是访问一个页面。
我的解决方案是为 selenium 驱动程序创建一个 HTTP 客户端并指定更长的超时时间:
Capybara.register_driver :chrome do |app|
client = Selenium::WebDriver::Remote::Http::Default.new
client.read_timeout = 120
Capybara::Selenium::Driver.new(app, {browser: :chrome, http_client: client})
end
使用我自己的访问方法版本解决了类似问题:
def safe_visit(url)
max_retries = 3
times_retried = 0
begin
visit url
rescue Net::ReadTimeout => error
if times_retried < max_retries
times_retried += 1
puts "Failed to visit #{url}, retry #{times_retried}/#{max_retries}"
retry
else
puts error.message
puts error.backtrace.inspect
exit(1)
end
end
end
如果你需要为 headless 配置它,你需要执行以下操作 chrome
Capybara.register_driver :headless_chrome do |app|
client = Selenium::WebDriver::Remote::Http::Default.new
client.timeout = 120 # instead of the default 60
options = Selenium::WebDriver::Chrome::Options.new
options.headless!
Capybara::Selenium::Driver.new(app, {
browser: :chrome,
http_client: client,
options: options
})
end
Capybara.default_driver = :headless_chrome
Capybara.javascript_driver = :headless_chrome
在功能中传递无头参数对我不起作用。
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w[headless disable-gpu] }
)
这里是more details为什么 headless in capabilities 不起作用的原因。
我正在使用 Capybara、selenium-webdriver gem 和 chromedriver 来驱动我的 javascript 启用测试。
问题是我们大约 50% 的构建由于 Net::ReadTimeout
错误而失败。起初这表现为 'could not find element' 错误,但在我将 Capybara 的默认最长等待时间提高到 30 秒后,我开始看到超时。
我检查了超时发生时的屏幕截图,它停留在我们在使用 Javascript 函数 location.reload()
重新加载页面之前简要显示的 'Successfully logged in' 模态。
我在本地 运行 进行了测试,有时可以重现,也 运行domly。有时它会通过此模式压缩并重新加载如此之快你几乎看不到它,而其他时候它会永远挂起。
我觉得这不是资产编译问题,因为此时网站已经加载,以便用户访问登录表单。
想知道是否有人以前见过此问题并知道解决方案。
具体代码:
visit login_path
page.within '#sign-in-pane__body' do
fill_in 'Email', with: user.email
click_button 'Submit'
end
expect(page).to have_content 'Enter Password'
page.within '#sign-in-pane__body' do
fill_in 'Password', with: user.password
click_button 'Submit'
end
expect(page).to have_text 'Home page landing text'
挂断发生在 click_button 'Submit'
和等待主页文本之间。
导致超时的逻辑流程是用户提交登录表单,我们等待服务器呈现一个 .js.erb
模板,该模板在成功登录后触发 JS 事件。当触发发生时,我们会显示一个模式,说明登录成功,然后执行 location.reload()
.
事实证明,这并不是在 JS 中执行 location.reload()
所独有的。有时只是访问一个页面。
我的解决方案是为 selenium 驱动程序创建一个 HTTP 客户端并指定更长的超时时间:
Capybara.register_driver :chrome do |app|
client = Selenium::WebDriver::Remote::Http::Default.new
client.read_timeout = 120
Capybara::Selenium::Driver.new(app, {browser: :chrome, http_client: client})
end
使用我自己的访问方法版本解决了类似问题:
def safe_visit(url)
max_retries = 3
times_retried = 0
begin
visit url
rescue Net::ReadTimeout => error
if times_retried < max_retries
times_retried += 1
puts "Failed to visit #{url}, retry #{times_retried}/#{max_retries}"
retry
else
puts error.message
puts error.backtrace.inspect
exit(1)
end
end
end
如果你需要为 headless 配置它,你需要执行以下操作 chrome
Capybara.register_driver :headless_chrome do |app|
client = Selenium::WebDriver::Remote::Http::Default.new
client.timeout = 120 # instead of the default 60
options = Selenium::WebDriver::Chrome::Options.new
options.headless!
Capybara::Selenium::Driver.new(app, {
browser: :chrome,
http_client: client,
options: options
})
end
Capybara.default_driver = :headless_chrome
Capybara.javascript_driver = :headless_chrome
在功能中传递无头参数对我不起作用。
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w[headless disable-gpu] }
)
这里是more details为什么 headless in capabilities 不起作用的原因。