2015-01-18 12 views
5

Ich habe seltsame Probleme mit einigen meiner Feature-Tests mit Capybara mit Poltergeist-Treiber. Der Test sollte einen einfachen Checkout in meinem Online-Shop durchführen. Sie alle gehen gut auf meinem lokalen MacBook sowie auf einer Ubuntu Vagrants Box. Bei CI-Diensten wie Codeship, Wercker oder Semaphore scheitern sie jedoch mit dem gleichen Fehler.Capybara Poltergeist Feature-Test scheitert an CI, aber passiert lokal

Meine spec:

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 

Der Fehler, den ich auf CI bekommen ist:

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

Für mich diese super seltsam ist, als die erste Erwartung "erwarten (page.body). to have_link ('Test Product 1') 'scheint zu bestehen, aber dann scheitert es im nächsten Schritt, wo es eigentlich auf den Link klicken sollte, der gerade auf der Seite vorhanden war?

Ich habe dann Poltergeist Treiber wie folgt neu konfiguriert, um mehr Debug-Informationen zu sammeln.

Snippet 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 

Jetzt kann ich auf CI-Konsole sehen, dass der Test erfolgreich meine products_path und die erwartete HTML-Seite besucht (einschließlich meinem Link sollte es klicken) zurückgegeben wird. ich den Rest der HTML-Antwort entfernt, um es besser lesbar zu machen:

{"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} 

Die letzten Aktionen zwei finden wiederholen, bis Capybara seine Timeout erreicht hat, dann schlägt der Test fehl. Ich überprüfte das Xpath Capybara über einige Online-Xpath-Validatoren, aber wie erwartet entspricht es dem HTML-Link. Ich habe auch capybara-screenshot gem verwendet, um den HTML-Body bei Ausfall zu entleeren und der fragliche Link ist auch vorhanden.

Warum funktioniert der Test noch? Gibt es eine Race Condition, die mir nicht bekannt ist? Warum passiert es lokal, aber auf keinem der CI-Dienste?

Hier sind meine Perle Version:

  • Capybara (2.4.4)
  • Capybara-Screenshot (1.0.3)
  • database_cleaner (1.3.0)
  • factory_girl (4.5.0)
  • factory_girl_rails (4.5.0)
  • poltergeist (1.5.1)
  • Schienen (4.1.8)
  • rspec (3.1.0)
  • rspec-Schienen (3.1.0)
  • und PhantomJS 1.9.7

Antwort

0

Während ich dies nicht wiedergeben kann, ich erinnere mich, vor diesem Problem.Ich glaube, Ihre Linie:

expect(page.body).to have_link('Test Product 1') 

vorbei, weil der Link buchstäblich auf dem Körper der HTML-Seite ist, auch wenn es aufgrund von CSS oder JS Verhalten versteckt werden kann. Die Zeile:

click_link('Test Product 1') 

überprüft auf jeden Fall Sichtbarkeit, bevor Sie auf den Link klicken. Sie sollten Ihre spec_helper.rb Konfigurationen überprüfen, um sicherzustellen:

Capybara.ignore_hidden_elements = true 

vorhanden ist, so dass die erste Zeile würde nicht passieren. Ich glaube, ich hatte auch die erste Zeile ich erwähnte zu ändern:

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

Sobald Sie dies tun, die erste Zeile blockiert der Thread und wartet, bis die Verbindung sichtbar werden. Dann wird der Rest des Tests bestehen.

Hoffe das löst es.

+0

In der Tat, wenn ich 'Capybara.ignore_hidden_elements = true' einstellen, scheitert sogar die erste Erwartung. Das Element scheint also nicht sichtbar zu sein. Wenn ich jedoch 'expect (page) .to have_link ('Test Product 1') 'setze, schlägt es immer noch fehl, da es blockiert, bis der Capybara seine Zeitüberschreitung erreicht. Aus irgendeinem Grund werden die Elemente nie sichtbar. – philkry