在将Rails从4.2升级到5.2后,我的测试在开发服务器中运行时被卡在一个请求上,我在运行测试服时遇到失败。
Failures:
1) cold end overview shows cold end stats
Failure/Error: example.run
RuntimeError:
Requests did not finish in 60 seconds
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/capybara-2.18.0/lib/capybara/server.rb:94:in `rescue in wait_for_pending_requests'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/capybara-2.18.0/lib/capybara/server.rb:91:in `wait_for_pending_requests'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/capybara-2.18.0/lib/capybara/session.rb:130:in `reset!'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/capybara-2.18.0/lib/capybara.rb:314:in `block in reset_sessions!'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/capybara-2.18.0/lib/capybara.rb:314:in `reverse_each'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/capybara-2.18.0/lib/capybara.rb:314:in `reset_sessions!'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/capybara-2.18.0/lib/capybara/rspec.rb:22:in `block (2 levels) in <top (required)>'
# ./spec/spec_helper.rb:43:in `block (3 levels) in <top (required)>'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/database_cleaner-1.6.2/lib/database_cleaner/generic/base.rb:16:in `cleaning'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/database_cleaner-1.6.2/lib/database_cleaner/base.rb:98:in `cleaning'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/database_cleaner-1.6.2/lib/database_cleaner/configuration.rb:86:in `block (2 levels) in cleaning'
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/database_cleaner-1.6.2/lib/database_cleaner/configuration.rb:87:in `cleaning'
# ./spec/spec_helper.rb:37:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Timeout::Error:
# execution expired
# /home/asnad/.rvm/gems/ruby-2.5.0/gems/capybara-2.18.0/lib/capybara/server.rb:92:in `sleep'
Top 1 slowest examples (62.59 seconds, 97.0% of total time):
cold end overview shows cold end stats
62.59 seconds ./spec/features/cold_end_overview_spec.rb:13
Finished in 1 minute 4.51 seconds (files took 4.15 seconds to load)
1 example, 1 failure
我的spec_helper.rb具有配置
RSpec.configure do |config|
config.include FactoryBot::Syntax::Methods
config.around(:each) do |example|
DatabaseCleaner[:active_record].clean_with(:truncation)
DatabaseCleaner.cleaning do
if example.metadata.key?(:js) || example.metadata[:type] == :feature
# VCR.configure { |c| c.ignore_localhost = true }
WebMock.allow_net_connect!
VCR.turn_off!
VCR.eject_cassette
example.run
else
# WebMock.disable_net_connect!
VCR.turn_on!
cassette_name = example.metadata[:full_description]
.split(/\s+/, 2)
.join('/')
.underscore.gsub(/[^\w\/]+/, '_')
# VCR.configure { |c| c.ignore_localhost = false }
VCR.use_cassette(cassette_name) { example.run }
VCR.turn_off!
WebMock.allow_net_connect!
end
end
end
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.filter_run :focus
config.run_all_when_everything_filtered = true
config.example_status_persistence_file_path = "spec/examples.txt"
if config.files_to_run.one?
config.default_formatter = 'doc'
end
# Print the 10 slowest examples and example groups at the
# end of the spec run, to help surface which specs are running
# particularly slow.
config.profile_examples = 10
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = :random
# Seed global randomization in this process using the `--seed` CLI option.
# Setting this allows you to use `--seed` to deterministically reproduce
# test failures related to randomization by passing the same `--seed` value
# as the one that triggered the failure.
Kernel.srand config.seed
end
# Selenium::WebDriver.logger.level = :debug
# Selenium::WebDriver.logger.output = 'selenium.log'
Capybara.register_driver :selenium_chrome_headless do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(chromeOptions: { args: %w[headless no-sandbox disable-dev-shm-usage disable-gpu window-size=1200,1500] }, loggingPrefs: { browser: 'ALL' })
Capybara::Selenium::Driver.new(app, browser: :chrome, desired_capabilities: capabilities)
end
Chromedriver.set_version '2.39'
Capybara.javascript_driver = :selenium_chrome_headless
Capybara::Screenshot.prune_strategy = :keep_last_run
在我的规范中,行sign_in current_user
花费了很多时间,实际上它重定向到页面,即使在开发环境中工作很长时间也没有得到响应。
如果您需要其他任何东西,可能是什么原因,请发表评论。
答案 0 :(得分:0)
从4.2升级到5.1以及现在是5.2之后,我才刚到这里,在测试中看到了同样的事情,当我在binding.pry
的请求中冻结测试时,我得到消息Requests did not finish in 60 seconds
。多么棒的故事,跳到tl; dr的结尾(我可能已经知道了。)
现在,我已逐步升级了所有宝石,这样我就可以保持二等分的能力并观察这种有趣变化的来源。在从chromedriver-helper
切换为报告的新webdrivers
宝石之后,我才注意到这个新的60秒超时,但这似乎无关,因为我搜索了任何超时的webdriver或60秒值,并且仅找到对不相关的Pull Request#60的引用(修正了Issue#59)。
我在gem的源目录中检查了此消息Requests did not finish in 60 seconds
,发现它实际上不是Capybara的较旧版本,但是它已从至少3.9.0的版本中提出,并且lib/capybara/server.rb
中最新的3.24.0版本中。
那里使用的对象有一个计时器,您可以在助手中找到它的接口:
此特殊消息是从方法wait_for_pending_requests
发出的,该方法将硬60传递到命名参数:expire_in
中,然后发送服务器线程中遇到的任何错误。这意味着时间是不可配置的,虽然等待我的测试有点不方便,但是等待60秒是等待正在进行的Web请求完成的合理时间长度。
该方法仅在一个位置reset!
中调用,您可以在capybara/session.rb
中找到该方法:https://github.com/teamcapybara/capybara/blob/320ee96bb8f63ac9055f7522961a1e1cf8078a8a/lib/capybara/session.rb#L126
重置!该方法是一个有趣的方法,随附了一些有关如何使用的文档。如果@server&.wait_for_pending_requests
在请求中有一个活动的服务器线程,则它可能会调用wait_for_pending_requests,然后引发throw_server_error!仅当@server&.error
为真时,此操作类似。
现在,我们发现该重置!带有两个别名,每当水豚呼叫reset!
或cleanup!
时,都会收到此消息reset_session!
。在这一点上,我们也许可以理解发生了什么,但是当我使用chromedriver-helper和硒测试几年了,但是仍然记得60秒钟没有超时时,这仍然有些神秘。我犹豫要把手指指向webdriver,但是对于为什么这个超时是新的,我没有其他答案。我还没有做任何可以解决这个问题的事情,只是升级到该gem和其他任何gem,并清除弃用警告。
在Rails 5.1+中,似乎有可能重置水豚呼叫!比测试示例之间的更多,甚至更多。尤其是当您阅读了该方法的文档并考虑了单页焦点之后,并考虑了reset!
文档告诉您该方法不会重置的所有内容时,请清除浏览器缓存/ HTML 5本地存储/ IndexedDB / Web SQL数据库/等 —也许我在想像它,这并不是什么新鲜事。但是我在想它可以通过多种方式调用reset!而不是停留在此超时代码中,这可能与驱动程序有关。
在升级Rails时,您是否偶然变成了webdrivers
宝石?
编辑:为了确定起见,我还原为chromedriver-helper,不是吗。实际发生的情况是我的测试在一个线程中失败,但是服务器未打开binding.pry
会话。 Capybara已进入下一个测试,因此要进行一个名为reset!
的新会话,但是60秒钟后,我仍处于撬会话中,服务器仍未准备好响应根请求。我感觉水豚的线程行为已更改,在我的内存中,在服务器请求期间打开的撬会话将阻止测试失败,直到返回为止。但这显然不再发生了。
您是怎么到达这里的?不幸的是我不知道,但这是对收到该消息时正在发生的事情的公正描述。