Capybara Poltergeist功能测试在CI上失败但在本地传递

phi*_*kry 5 capybara rspec-rails poltergeist ruby-on-rails-4

我使用带有恶作剧驱动程序的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
Run Code Online (Sandbox Code Playgroud)

我在CI上遇到的错误是:

2) Checkout checks out via CreditCard
Failure/Error: click_link('Test Product 1')
Capybara::ElementNotFound:
  Unable to find link "Test Product 1"
Run Code Online (Sandbox Code Playgroud)

对我来说,这是非常奇怪的,因为第一个期望' 期望(page.body).to has_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
Run Code Online (Sandbox Code Playgroud)

现在我可以在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}
Run Code Online (Sandbox Code Playgroud)

最后两个发现动作重复,直到Capybara达到超时,然后测试失败.我通过一些在线xpath验证器仔细检查了Capybara使用的xpath,但正如预期的那样,它与HTML链接相匹配.我还使用capybara-screenshot gem在失败时转储HTML正文,并且还存在相关链接.

那么为什么测试仍然失败?有没有我不知道的种族情况?为什么它在本地传递但没有CI服务?

这是我的宝石版本:

  • 水豚(2.4.4)
  • capybara-screenshot(1.0.3)
  • database_cleaner(1.3.0)
  • factory_girl(4.5.0)
  • factory_girl_rails(4.5.0)
  • 恶作剧者(1.5.1)
  • 铁轨(4.1.8)
  • rspec(3.1.0)
  • rspec-rails(3.1.0)
  • 和phantomjs 1.9.7

Ami*_*ana 0

虽然我无法重现这个问题,但我记得以前遇到过这个问题。我相信你的台词:

expect(page.body).to have_link('Test Product 1')
Run Code Online (Sandbox Code Playgroud)

正在通过,因为链接实际上位于 html 页面的主体上,即使它可能由于 CSS 或 JS 行为而被隐藏。然而,该行:

click_link('Test Product 1')
Run Code Online (Sandbox Code Playgroud)

在点击链接之前一定要检查可见性。您应该检查您的spec_helper.rb配置以确保:

Capybara.ignore_hidden_elements = true
Run Code Online (Sandbox Code Playgroud)

存在,因此第一行不会通过。我想我还必须将我提到的第一行更改为:

# Change page.body to page, to look at the rendered page, not the literal one
expect(page).to have_link('Test Product 1')
Run Code Online (Sandbox Code Playgroud)

一旦执行此操作,第一行就会阻塞线程并等待,直到链接变得可见。然后其余的测试就会通过。

希望这能解决它。