2013-01-10 4 views
8

Ich habe eine alte Rails-Anwendung auf Version 3.2.11 aktualisiert, die eine Vielzahl von Request-Spezifikationen mit Capybara Version 1.0.1 geschrieben und mit dem Selenium-Treiber ausgeführt hat . Die Datenbank wird nach jedem Test mit database_cleaner mithilfe der Trunkierungsstrategie bereinigt.Upgrade von Capybara von 1.0.1 auf 1.1.4 macht database_cleaner meine Spezifikationen zu brechen

Ich möchte Poltergeist anstelle von Selen und aufgewerteten Capybara von 1.0.1 bis 1.1.4 verwenden, um die neueste Version von Poltergeist verwenden zu können. Nur das Ändern des Capybara-Edelsteins (und seiner Abhängigkeiten) führte zu Problemen beim Ausführen meiner Spezifikationen.

Ich bekomme immer wieder Deadlock-Fehler von meiner Postgresql-Datenbank im Bereinigungshandler nach jeder Spezifikation. Mein spec_helper ist ziemlich einfach und sieht wie folgt aus:

RSpec.configure do |config| 
    config.mock_with :rspec 

    config.use_transactional_fixtures = false 

    config.before(:suite) do 
    DatabaseCleaner.strategy = :truncation 
    DatabaseCleaner.clean_with(:truncation) 
    end 

    config.before(:each) do 
    DatabaseCleaner.start 
    end 

    config.after(:each) do 
    DatabaseCleaner.clean 
    end 
end 

Der Fehler, den ich bekommen ist wie folgt:

An error occurred in an after hook 
    ActiveRecord::StatementInvalid: PG::Error: ERROR: deadlock detected 
DETAIL: Process 41747 waits for AccessExclusiveLock on relation 17612 of database 16396; blocked by process 41752. 
Process 41752 waits for RowExclusiveLock on relation 17529 of database 16396; blocked by process 41747. 
HINT: See server log for query details. 
: ALTER TABLE "aaa" ENABLE TRIGGER ALL;ALTER TABLE "bbbb" ENABLE TRIGGER ALL;ALTER TABLE "ccc" ENABLE TRIGGER ALL; 
    occurred at /xxx/.bundle/gems/activerecord-3.2.11/lib/active_record/connection_adapters/postgresql_adapter.rb:652:in `async_exec' 

I factory verwenden Testdaten zu schaffen, aber sonst nichts IMO Besonderes.

Ich konnte nicht herausfinden, was das andere Ende von Deadlock enthält, das von database_cleaner erstellt wird. Irgendwelche Ideen, um das herauszufinden, sind sehr willkommen.

Kennt jemand Änderungen zwischen Capybara 1.0.1 und 1.1.4, die sich geändert haben und diese Probleme verursacht haben?

+0

ich eigentlich experien ced das Gegenteil. Ich hatte in meinen Tests zeitweise Deadlocks, bis ich von 1.1.2 auf Capybara 1.1.4 umstieg. Entschuldigung, mein Kommentar ist nicht hilfreicher. =/ –

+0

Nun, ich bin froh, dass ich nicht die einzige bin, die Deadlock-Probleme erlebt :-) Ich verstehe einfach nicht, warum zwei Threads gleichzeitig auf die Tabellen zugreifen. DatabaseClean sollte nur funktionieren, nachdem die eigentlichen Tests abgeschlossen sind ... – HakonB

+0

Oh, das ist vielleicht eine blöde Frage, aber hast du schon versucht, dein DatabaseCleaner-Juwel zu aktualisieren? Außerdem denke ich für FWIW, dass die Fehler erst dann aufgetreten sind, nachdem wir delayed_job benutzt haben (obwohl wir es für die Tests abgeschaltet haben). –

Antwort

5

Ich habe, um dieses Problem in Gurken von

sleep 0.2 

am Ende des Schritts (oder in Ihrem Fall „spec“) platzieren, das einige AJAX Sachen tut. Ich stelle mir vor, was passiert ist, dass Gurke/Rspec Datenbank Reiniger aufruft, während der JS-Treiber immer noch auf die Ajax-Antwort wartet.

+0

Arbeitete für mich. Es scheint seltsam, dass es nicht mehr Leute gibt, die darauf stoßen. –

+0

Arbeitete auch für mich. Ist eine echte Lösung in Sicht? – morgler

+0

Das funktioniert, verlangsamt aber den Test unnötig und kann manchmal fehlschlagen. Die Lösung besteht darin, am Ende des Tests einen Aufruf an die Capybara API (wie has_content?) Zu senden. Ich habe in der Antwort unten ausgearbeitet. –

5

Der Fix ist nicht zu verwenden sleep, aber nur Capybara API-Methoden zu verwenden, wie sie auf das warten, was erwartet wird.

Unten Linie 2 nicht (wie current_path ist nicht warten, aber der Linie 3 Werke (wie has_selector? wartet). Der Link zu Jonas Nicklas' Artikel weiter unten erklärt es gut.

click_on 'signup_button' # Which does an AJAX redirect to /dashboard 
assert_equal dashboard_path, current_path # This causes the deadlock error as Capybara doesn't wait. 
assert page.has_selector?("#dashboard") # This works as it causes Capybara to wait for the new page. 

http://www.elabs.se/blog/53-why-wait_until-was-removed-from-capybara

+0

Ich bin mir ziemlich sicher, dass dies nur in Capybara 2 funktioniert. Hast du es in Capybara <2 probiert? –

1

die Lösung, die wir verwenden, ist etwas auf der Seite zu finden, die in Reaktion auf einen erfolgreichen ajax-Aufruf ändern sollten so etwas wie:.

click_on('Save') 
expect(page).to have_content('Saved') 
Verwandte Themen