Ruby Selenium Capybara没有超时

时间:2018-05-07 21:16:10

标签: ruby selenium selenium-webdriver rspec capybara

我的规格问题没有超时。我的一些规格已达到某一点,只是悬挂。我确定其中一个规格导致它被破坏有问题,我无法弄清楚为什么当我定义超时时它们只是无限期地挂起......

# frozen-string-literal: true
require 'rspec'
require 'capybara/rspec'
require 'capybara/dsl'
require 'selenium-webdriver'
require 'site_prism'

Dir[File.dirname(__FILE__) + '/page_objects/*/*.rb'].each do |page_object|
  require page_object
end

def wait_for_ajax
  Timeout.timeout(Capybara.default_max_wait_time) do
    loop until page.evaluate_script('jQuery.active').zero? && page.has_no_css?(".k-loading-color")
  end
end

def whole_page
  Capybara.current_session
end

Capybara.register_driver :selenium do |app|
  Capybara::Selenium::Driver.new(app, browser: :chrome)
end

Capybara.default_driver = :selenium
Capybara.app_host = #REDACTED
Capybara.default_max_wait_time = 20

RSpec.configure do |config|
  config.before(:each) do
    config.include Capybara::DSL
  end

  config.after(:each) do
    Capybara.reset_sessions! 
  end
end

1 个答案:

答案 0 :(得分:2)

你没有提到它挂在哪个命令上,但我会猜测它在你的wait_for_ajax方法中。如果是这样的话,那是因为你使用的是Timeout.timeout,这是Ruby提供的最危险的方法。它的工作方式是启动第二个线程,然后在发生超时时在原始线程中引发异常。问题是原始线程中的任何地方都可能发生异常,这意味着如果timeout调用中的块正在做任何非常重要的事情,它可能最终处于完全不可恢复的状态(网络通信等)。基本上Timeout.timeout只能安全地使用,并且非常详细地了解它所发生的每一件小事,这意味着它永远不会被用于对第三方库的任何调用。相反,如果您需要超时,您应该只使用计时器并休眠。像

这样的东西
def wait_for_ajax
  start = Time.now
  until page.evaluate_script('jQuery.active').zero? && page.has_no_css?(".k-loading-color", wait: false) do
    sleep 0.1
    raise <Some Error> if (Time.now - start) > Capybara.default_max_wait_time
  end
end

据说你真的不应该wait_for_ajax使用可用的UI和正确编写的测试。

此外,通过加入capybara/rspec,您已经为reset_sessions设置了在每次测试后调用,并且Capybara::DSL要包含在测试类型中,它应该被包含在 - https://github.com/teamcapybara/capybara/blob/master/lib/capybara/rspec.rb#L9 - 所以通过添加自己的after块,您只需在每次测试后调用reset_sessions两次,这只是浪费时间。