我在使用带有恶作剧驱动程序的Capybara的一些功能测试时遇到了奇怪的问题。 测试应该在我的网上商店进行简单的结账。 它们都在我当地的MacBook以及Ubuntu流浪盒上都很好。但是对于像Codeship,Wercker或Semaphore这样的CI服务,它们会出现同样的错误。
我的规格:
require 'rails_helper'
describe 'Checkout' do
let!(:product) { FactoryGirl.create(:product) }
it 'checks out via CreditCard', js: true do
visit products_path
expect(page.body).to have_link('Test Product 1')
click_link('Test Product 1')
#rest of spec ommitted
end
end
我在CI上遇到的错误是:
2) Checkout checks out via CreditCard
Failure/Error: click_link('Test Product 1')
Capybara::ElementNotFound:
Unable to find link "Test Product 1"
对我而言,这是非常奇怪的,因为第一个期望'期望(page.body).to have_link('测试产品1')'似乎通过但是它在下一步失败了它应该实际点击它确保在页面上出现的链接?
然后我按如下方式重新配置了poltergeist驱动程序以收集更多调试信息。
rails_helper.rb的片段:
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, {js_errors: false,
#inspector: true,
phantomjs_logger: Rails.logger,
logger: nil,
phantomjs_options: ['--debug=no', '--load-images=no', '--ignore-ssl-errors=yes', '--ssl-protocol=TLSv1'],
debug: true
})
end
Capybara.server_port = 3003
Capybara.app_host = 'http://application-test.lvh.me:3003' # lvh.me always resolves to 127.0.0.1
Capybara.javascript_driver = :poltergeist
Capybara.current_driver = :poltergeist
Capybara.default_wait_time = 5
现在我可以在CI控制台上看到测试成功访问了我的products_path,并且正在返回预期的html页面(包括我应该点击的链接)。 我删除了其余的HTML响应以使其更具可读性:
{"name"=>"visit", "args"=>["http://application-test.lvh.me:3003/products"]}
{"response"=>{"status"=>"success"}}
{"name"=>"body", "args"=>[]}
{"response"=>"--- snip --- <div class=\"info\">\n<a class=\"name color-pomegranate\" href=\"/en/products/6\">\nTest Product 1\n</a>\n850,00 \n</div> --- snap ---"}
{"name"=>"find", "args"=>[:xpath, ".//a[./@href][(((./@id = 'Test Product 1' or normalize-space(string(.)) = 'Test Product 1') or ./@title = 'Test Product 1') or .//img[./@alt = 'Test Product 1'])]"]}
{"response"=>{"page_id"=>4, "ids"=>[0]}}
{"name"=>"visible", "args"=>[4, 0]}
{"response"=>false}
{"name"=>"find", "args"=>[:xpath, ".//a[./@href][(((./@id = 'Test Product 1' or contains(normalize-space(string(.)), 'Test Product 1')) or contains(./@title, 'Test Product 1')) or .//img[contains(./@alt, 'Test Product 1')])]"]}
{"response"=>{"page_id"=>4, "ids"=>[1]}}
{"name"=>"visible", "args"=>[4, 1]}
{"response"=>false}
最后两个发现动作重复,直到Capybara达到超时,然后测试失败。 我通过一些在线xpath验证器仔细检查了Capybara使用的xpath,但正如预期的那样,它与HTML链接相匹配。 我还使用capybara-screenshot gem在失败时转储HTML正文,并且还存在相关链接。
那为什么测试仍然失败? 有没有我不知道的种族情况?为什么它在本地传递但没有传递给CI服务?
以下是我的宝石版本:
答案 0 :(得分:0)
虽然我无法重现这一点,但我记得以前遇到过这个问题。我相信你的路线:
expect(page.body).to have_link('Test Product 1')
正在传递,因为链接实际上位于html页面的主体上,即使它可能由于CSS或JS行为而被隐藏。但是,行:
click_link('Test Product 1')
在点击链接之前肯定会检查可见性。您应该检查spec_helper.rb配置以确保:
Capybara.ignore_hidden_elements = true
存在,因此第一行不会通过。我想我也必须改变我提到的第一行:
# Change page.body to page, to look at the rendered page, not the literal one
expect(page).to have_link('Test Product 1')
执行此操作后,第一行会阻塞线程并等待链接变为可见。然后剩下的测试将通过。
希望这能解决它。