恶作剧者似乎并不等待幻影加载到水豚

时间:2017-01-19 03:50:34

标签: ruby selenium rspec phantomjs capybara

我试图使用Capybara,Selenium,Capybara / webkit和Poltergeist混合运行一些rspec测试。我需要它在某些情况下无头运行,而不是使用xvfb来使webkit工作。我可以使用selenium或poltergeist作为phantomjs的驱动程序。我遇到的问题是我的测试与selenium和firefox或chrome运行良好但是当我尝试phantomjs时,元素总是显示为未找到。在调查了一段时间并在capybara中使用page.save_screenshot后,我发现当驱动程序告诉它找到元素时,phantomjs浏览器没有被加载,因此它没有返回任何内容。我可以通过在< gem_path> /capybara/poltergeist/driver.rb中编辑poltergeist源来修复此问题,如下所示

def visit(url)
  if @started
    sleep_time = 0
  else
    sleep_time = 2
  end
  @started = true
  browser.visit(url)
  sleep sleep_time
end

对于这个问题来说,这显然不是一个理想的解决方案,并且它不能用硒作为幻象的驱动因素。无论如何,我可以告诉司机等待幻影做好准备吗?

更新:

我能够通过更改我包含Capybara :: DSL的位置来运行它。我将它添加到RSpec.configure块,如下所示。

RSpec.configure do |config|
  config.include Capybara::DSL

然后我将页面对象传递给我创建的用于与网页ui进行交互的所有类。

示例类现在看起来像这样

module LoginUI
  require_relative 'webpage'

  class LoginPage < WebPages::Pages
    def initialize(page, values = {})
      super(page)
    end

    def visit
      browser.visit(login_url)
    end

    def login(username, password)
      set_username(username)
      set_password(password)
      sign_in_button
    end

    def set_username(username)
      edit = browser.find_element(@selectors[:login_edit])
      edit.send_keys(username)
    end

    def set_password(password)
      edit = browser.find_element(@selectors[:password_edit])
      edit.send_keys(password)
    end

    def sign_in_button
      browser.find_element(@selectors[:sign_in_button]).click
    end
  end
end

网页模块看起来像这样

module WebPages
  require_relative 'browser'
  class Pages
    def initialize(page)
      @page = page
      @browser = Browser::Browser.new
    end

    def browser
      @browser
    end

    def sign_out
      browser.visit(sign_out_url)
    end
  end
end

浏览器模块看起来像这样

module Browser
  class Browser
    include Capybara::DSL
    def refresh_page
      page.evaluate_script("window.location.reload()")
    end

    def submit(locator)
      find_element(locator).click
    end

    def find_element(hash)
      page.find(hash.keys.first, hash.values.first)
    end

    def find_elements(hash)
      page.find(hash.keys.first, hash.values.first, match: :first)
      page.all(hash.keys.first, hash.values.first)
    end

    def current_url
      return page.current_url
    end
  end
end

虽然这有效但我不想在RSpec中包含Capybara :: DSL或者必须在类中包含页面对象。这些类已经删除了一些示例,但显示了一般结构。理想情况下,我希望浏览器模块包含Capybara :: DSL,并能够处理与Capybara的所有交互。

2 个答案:

答案 0 :(得分:1)

您的更新完全更改了问题,因此我添加了第二个答案。如果您不在浏览器类之外调用任何Capybara方法,则无需在您的RSpec配置中包含Capybara :: DSL,就像没有必要通过“页面”一样。如果您将所有Capybara交互限制为您的浏览器类,则为您的所有Pages类。需要注意的一点是,Capybara :: DSL提供的page方法只是Capybara.current_session的别名,因此从技术上讲,您可以随时调用它。

您不会在代码中显示您如何处理页面内容的任何断言/期望 - 因此,根据您的操作方式,您可能需要包含Capybara::RSpecMatchers在您的RSpec配置和/或您的WebPages :: Pages类中。

您的示例代码会立即弹出一些问题,首先是您的Browser#find_elements(假设我正在阅读您首先正确使用find的意图)应该只是

def find_elements(hash)
  page.all(hash.keys.first, hash.values.first, minimum: 1)
end

其次,您的LoginPage#login方法应该对视觉更改有一个断言/期望,表明登录成功为最后一行(验证某些消息是否在菜单中显示/记录/等),以确保浏览器具有在测试继续进行之前收到了auth cookies等。这条线的样子取决于你如何构建你的期望。

如果这不能回答您的问题,请提供一个具体的示例,说明您没有为您工作的内容,因为您所显示的代码都没有表明需要Capybara :: DSL被列入您说不想要的任何一个地方。

答案 1 :(得分:0)

Capybara并不依赖于完成的访问,相反,查找者和匹配者将重试到指定的时间段,直到他们成功。您可以通过增加Capybara.default_max_wait_time的值来增加这段时间。默认情况下,等待的唯一方法是firstall,但可以通过指定任何计数选项等待/重试

first('.some_class', minimum: 1)  # will wait up to Capybara.default_max_wait_time seconds for the element to exist on the page.

虽然你应该总是首先选择find而不是首先/全部

如果增加最长等待时间并不能解决您的问题,请添加一个无法解决问题的测试示例。