2013-05-17 18 views
51

contest_entry_spec.rbSchienen rspec vor allem vs vor jedem

require 'spec_helper' 

    describe ContestEntry do 

     before(:all) do 
     @admission=Factory(:project_admission) 
     @project=Factory(:project_started, :project_type => @admission.project_type) 
     @creative=Factory(:approved_creative, :creative_category => @admission.creative_category) 
     @contest_entry=Factory(:contest_entry, :design_file_name => 'bla bla bla', :owner => @creative, :project => @project) 
     end 

     context 'non-specific tests' do 
     subject { @contest_entry } 
     it { should belong_to(:owner).class_name('User') } 
     it { should belong_to(:project) } 
     it { should have_many(:entry_comments) } 

     it { should validate_presence_of(:owner) } 
     it { should validate_presence_of(:project) } 
     it { should validate_presence_of(:entry_no) } 
     it { should validate_presence_of(:title) } 

     end 
end 

Wenn ich diese Tests laufen alles okey, aber wenn ich vor ändern (: all) bis vor (: jeder) wird jeder Test nicht bestanden Ich weiß nicht, warum es passiert?

Dies ist der Fehler

Failure/Error: @contest_entry=Factory(:contest_entry, :design_file_name => 'bla bla bla', :owner => @creative, :project => @project) 
    ActiveRecord::RecordInvalid: 
     Validation Failed: User is not allowed for this type of project 

Antwort

85

before(:all) läuft der Block eine Zeit vor allen Beispielen ausgeführt werden.

before(:each) läuft der Block einmal vor jedem Ihrer Angaben in der Datei

before(:all) die Variablen Instanz setzt @admission, @project, @creative, @contest_entry eine Zeit, bevor alle der it Blöcke ausgeführt werden.

:before(:each) setzt jedoch die Instanzvariablen im before-Block jedes Mal zurück, wenn ein it-Block ausgeführt wird.

Es ist eine subtile Unterscheidung aber wichtig

wieder

before(:all) 
#before block is run 
it { should belong_to(:owner).class_name('User') } 
it { should belong_to(:project) } 
it { should have_many(:entry_comments) } 

it { should validate_presence_of(:owner) } 
it { should validate_presence_of(:project) } 
it { should validate_presence_of(:entry_no) } 
it { should validate_presence_of(:title) } 

before(:each) 
# before block 
it { should belong_to(:owner).class_name('User') } 
# before block 
it { should belong_to(:project) } 
# before block 
it { should have_many(:entry_comments) } 
# before block 

# before block 
it { should validate_presence_of(:owner) } 
# before block 
it { should validate_presence_of(:project) } 
# before block 
it { should validate_presence_of(:entry_no) } 
# before block 
it { should validate_presence_of(:title) } 
+0

Lassen Sie mich wissen, wenn Sie etwas in Frage stellen. froh zu helfen – fontno

3

before(:all), die dafür sorgt, dass die Beispielbenutzer einmal erstellt werden, bevor alle Tests im Block. Dies ist eine Optimierung für die Geschwindigkeit.

14

Eines der wichtigsten Details von before :all ist, dass es nicht DB transactional ist. Dh alles innerhalb der before :all bleibt auf der db und Sie müssen manuell in der after :all Methode abreißen. Implikationen bedeuten, dass nach Abschluss der Testsuiten die Änderungen nicht für die nächsten Tests wiederhergestellt werden. Dies kann zu komplizierten Fehlern und Problemen mit einer Kreuzkontamination von Daten zwischen Tests führen. Denken Sie daran, wenn eine Ausnahme ausgelöst wird, wird der Rückruf after :all nicht aufgerufen.

Ein schneller Test zu demonstrieren:

1. Kürzen Sie Ihre entsprechenden DB-Tabelle diese dann versuchen,

before :all do 
    @user = Fabricate(:user, name: 'Happy Fun Pants') 
    end 

2. Beachten Datenbank danach, werden Sie feststellen, das Modell bleibt bestehen!? Das liegt daran, dass Sie after :all einschließen müssen, aber wenn eine Ausnahme in Ihrem Test auftritt, wird dieser Rückruf nicht erneut auftreten! Alle zukünftigen Tests werden jetzt gegen einen unsicheren DB-Status ausgeführt.

3. jetzt versuchen, diese,

before :each do 
    @user = Fabricate(:user, name: 'Happy Fun Pants') 
    end 

4.Nun ist die Datenbank bleibt frei von Daten nach der Testsuite ist abgeschlossen. Nicht gut mit CI/CD-Setups.

Konvolute Fehler können auftreten, wenn ein Test eine Ausnahme auslöst und nicht innerhalb von 100 endet (wodurch verhindert wird, dass die gesamte Testsuite abgeschlossen wird). Die Datenbank wird in einem unbekannten Zustand verlassen.

Kurz gesagt, before :each, ist wahrscheinlich, was Sie wollen. Ihre Tests werden etwas langsamer laufen, aber es sollte sich lohnen.

Details hier: https://relishapp.com/rspec/rspec-rails/docs/transactions See: Data created in before(:all) are not rolled back

Hoffnung, die einen anderen müden Reisenden hilft.

+0

Diese Tipps retten meinen Tag! Schreib einfach vorher nach vorher (: jedes) –

Verwandte Themen