我试图使用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的所有交互。
答案 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
的值来增加这段时间。默认情况下,等待的唯一方法是first
和all
,但可以通过指定任何计数选项等待/重试
first('.some_class', minimum: 1) # will wait up to Capybara.default_max_wait_time seconds for the element to exist on the page.
虽然你应该总是首先选择find
而不是首先/全部
如果增加最长等待时间并不能解决您的问题,请添加一个无法解决问题的测试示例。