1

Ich habe eine Feature/Integration-Spezifikation, die einen gesamten Benutzerfluss durchläuft. Am Ende dieses Benutzerflusses zeigt eine Seite in der App einige Datensätze aus meiner Postgres-Datenbank an. Wenn ich den Test selbst durchführe, passiert er. Ich kann sehen, wie es durch die verschiedenen Schritte richtig speichert, da der selen Treiber firefox öffnet: Capybara.current_driver = :selenium. Diese Spezifikation schlägt jedoch regelmäßig, fast vorhersehbar, fehl, wenn sie nach einer Reihe von Controller-Spezifikationen ausgeführt wird. In diesen Controller Angaben die einzige interessante Sache, die ich ist tue läuft diese Login-Funktion:Flockige Tests mit DatabaseCleaner und Transaktionen. Wie zu debuggen?

module DeviseMacros 
    def login_user 
    before(:each) do 
     @request.env['devise.mapping'] = Devise.mappings[:user] 
     user = create(:user_with_active_account) 
     sign_in user 
    end 
    end 
end 

So nenne ich es wie folgt aus:

describe AwesomeController do 
    login_user 

    it 'responds with 200' do 
    get :new 
    expect(response.status).to eq 200 
    end 
end 

Wenn nach einer Controller-Spezifikation ausführen kann ich sofort sehen, dass Der Test wird fehlschlagen, da bestimmte UI-Elemente angezeigt werden sollten, abhängig davon, was in der Datenbank enthalten ist und eindeutig nicht vorhanden sind.

Meine DatabaseCleaner Strategie ist wie folgt:

RSpec.configure do |config| 
    config.before(:suite) do 
    DatabaseCleaner.clean_with(:truncation) 
    end 

    config.before(:each) do 
    DatabaseCleaner.strategy = :transaction 
    end 

    config.before(:each, js: true) do 
    DatabaseCleaner.strategy = :truncation 
    end 

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

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

Durch Versuch und Irrtum ich

geändert
config.before(:each) do 
    DatabaseCleaner.strategy = :transaction 
    end 

zu

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

Und walla, es geht. Natürlich dauert die Testsuite jetzt doppelt so lange.

habe ich alle meine :selenium Tests mit js: true um getaggt für sie verwendet, um sicherzustellen :truncation ist aber, dass wirklich da :selenium spielt keine Rolle, schon jene fährt. Am wichtigsten ist jedoch, dass diese Feature-Spezifikation nach diesen Controller-Spezifikationen weiterhin fehlschlägt.

Wo sonst sollte ich suchen? Wie gehe ich mit dem Debugging vor?

Die einzige andere Sache, die ich hier drin haben, die in Beziehung gesetzt werden kann, ist:

# In spec/support/shared_db_connection.rb 
# https://gist.github.com/josevalim/470808 
class ActiveRecord::Base 
    mattr_accessor :shared_connection 
    @@shared_connection = nil 

    def self.connection 
    @@shared_connection || retrieve_connection 
    end 
end 

# Forces all threads to share the same connection. This works on 
# Capybara because it starts the web server in a thread. 
ActiveRecord::Base.shared_connection = ActiveRecord::Base.connection 

Ratschläge oder Ideen, wie es weitergehen würde mit Debugging sehr geschätzt.

Wenn Sie weitere Fragen haben, fragen Sie bitte. Danke

Update: 1. Juni 2016

Die genaue Codezeile, die den Fehler verursacht, ist:

module DeviseMacros 
    def login_user 
    before(:each) do 
     @request.env['devise.mapping'] = Devise.mappings[:user] 
     user = create(:user_with_active_account) 
     sign_in user # <----- THIS GUY RIGHT HERE! When removed, the ControllerSpec fails but the integration test passes. 
    end 
    end 
end 

So aus irgendeinem Grund scheint es, dass die DB mit diesem Controller spec schlagen (die verwendet :transaction Strategie) wirkt sich auf die Feature-Spezifikation (die :truncation Strategie verwendet).

Ich debattiere nur nicht die DB überhaupt in den Controller-Spezifikationen zu treffen, wenn ich versuche, einen Gerätebenutzer zu authentifizieren, was mit mir cool ist, aber ich denke, es sollte nicht so sein müssen. Irgendwelche Ideen, wie man vorgeht, wenn ich tatsächlich in der Lage sein möchte, die sign_in Methode zu verwenden?

Danke

+0

BTW, was passiert, wenn Sie verwenden überall die Transaktionsstrategie? Weil ich denke, dass dies der ActiveRecord-Patch ist, nicht wahr? – BoraMa

+0

@BoraMa Danke für die Vorschläge. Wenn ': transaction' überall benutzt wird, bekomme ich viel mehr Fehler, die mit der DB zu tun haben. Ich aktualisierte mit mehr Info über die Codezeile, die das obige Problem verursacht. Irgendwelche Ideen? –

+0

OK, ich würde auch für das Dumping dieses AR-Patches stimmen und versuchen, das Problem ohne es zu lösen. Können Sie Ihre 'sign_in' Methode posten? Übrigens erinnere ich mich vage daran, dass wir in der Vergangenheit ähnliche Probleme mit unseren Tests hatten. Am Ende haben wir die Tests auf zwei Testsuiten aufgeteilt: alle nicht JS und alle JS, und wir führen die beiden Testanzüge getrennt und ohne weitere Probleme aus. – BoraMa

Antwort

0

Entfernen Sie die gemeinsam genutzte Verbindung Hack, da es mehr Probleme verursacht als es wert ist, und aktualisieren Sie Ihre Datenbank-Reiniger Config auf die empfohlene eine aus der Datenbank Reiniger README - https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example

+0

Ich habe den shared_connection-Code entfernt und die database_cleaner-Regeln so aktualisiert, dass sie genau wie in Ihrem Link sind. Der Fehler tritt immer noch auf. Ich habe jedoch die genaue Codezeile gefunden, die den Fehler verursacht, und meine Frage oben aktualisiert. Gibt dir das mehr Ideen? –

+0

Die Lösung bestand darin, alle Feature-Spezifikationen zu durchlaufen und sie explizit mit einem Tag (: js) zu versehen, um sicherzustellen, dass alle Transaktionen verwenden. Stellt sich heraus, dass diese Fehler zufällig aus allen Feature-Spezifikationen kamen. Musste nur in den sauren Apfel beißen und mit langsameren Eigenschaften gehen. –