Rails测试失败请求在60秒内未完成

时间:2018-11-22 15:57:46

标签: ruby-on-rails-5 capybara selenium-chromedriver rspec-rails database-cleaner

在将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花费了很多时间,实际上它重定向到页面,即使在开发环境中工作很长时间也没有得到响应。 如果您需要其他任何东西,可能是什么原因,请发表评论。

1 个答案:

答案 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版本中。

那里使用的对象有一个计时器,您可以在助手中找到它的接口:

https://github.com/teamcapybara/capybara/blob/320ee96bb8f63ac9055f7522961a1e1cf8078a8a/lib/capybara/helpers.rb#L79

此特殊消息是从方法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秒钟后,我仍处于撬会话中,服务器仍未准备好响应根请求。我感觉水豚的线程行为已更改,在我的内存中,在服务器请求期间打开的撬会话将阻止测试失败,直到返回为止。但这显然不再发生了。

您是怎么到达这里的?不幸的是我不知道,但这是对收到该消息时正在发生的事情的公正描述。