Schienen rspec vor allen vs vor jedem

79

contest_entry_spec.rb

    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 durchführe, ist alles in Ordnung, aber wenn ich vor (: all) zu vor (: each) ändere, schlägt jeder Test fehl. 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
Johnny Cash
quelle

Antworten:

120

before(:all) führt den Block einmal aus, bevor alle Beispiele ausgeführt werden.

before(:each) Führt den Block einmal vor jeder Ihrer Angaben in der Datei aus

before(:all)Legt die Instanzvariablen @admission, @project, @creative, @contest_entryeinmal fest, bevor alle itBlöcke ausgeführt werden.

Allerdings :before(:each)setzt die Instanzvariablen in der vor jedem Block ein itBlock ausgeführt wird.

Es ist eine subtile Unterscheidung, aber wichtig

nochmal,

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) }
fontno
quelle
Weißt du, warum es mit vorher (: jeweils)
gescheitert ist
38

Ein wichtiges Detail von before :allist, dass es nicht DB ist transactional. Das heißt, alles in der before :allDatenbank bleibt bestehen, und Sie müssen die after :allMethode manuell herunterfahren .

Implikationen bedeuten, dass nach Abschluss der Testsuiten Änderungen nicht für spätere Tests zurückgesetzt werden. Dies kann zu komplizierten Fehlern und Problemen bei der Kreuzkontamination von Daten führen. Dh wenn eine Ausnahme ausgelöst wird, wird der after :allRückruf nicht aufgerufen.

Ist before: each jedoch DB-Transaktion.

Ein schneller Test, um zu demonstrieren:

1. Schneiden Sie die entsprechende DB-Tabelle ab und versuchen Sie Folgendes:

  before :all do
    @user = Fabricate(:user, name: 'Yolo')
  end

2. Beobachten Sie die Datenbank danach, das Modell bleibt bestehen !

after :allist nötig. Wenn in Ihrem Test jedoch eine Ausnahme auftritt, tritt dieser Rückruf nicht auf, da der Fluss unterbrochen wurde. Die Datenbank wird in einem unbekannten Zustand belassen, was insbesondere bei CI / CD-Umgebungen und automatisierten Tests problematisch sein kann.

3. Jetzt versuchen Sie dies,

  before :each do
    @user = Fabricate(:user, name: 'Yolo')
  end

4. Jetzt bleibt die Datenbank nach Abschluss der Testsuite ohne Daten . Weitaus besser und hinterlässt nach den Tests einen konsistenten Zustand.

Kurz gesagt, before :eachist wahrscheinlich das, was Sie wollen. Ihre Tests laufen etwas langsamer, aber die Kosten sind es wert.

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

Hoffe das hilft einem anderen müden Reisenden.

wired00
quelle
Diese Tipps retten meinen Tag! Schreiben Sie einfach vorher bis vorher (: jeweils)
Humberto Corrêa
4

before(:all)Dies stellt sicher, dass die Beispielbenutzer vor allen Tests im Block einmal erstellt werden. Dies ist eine Optimierung für die Geschwindigkeit.

Jazib Bashir
quelle
0

Eine Sache, die zu beachten ist, ist standardmäßig vor der Verwendung vor (: each), auch vor (: all) ist die Controller-Instanz nicht festgelegt, so dass die Controller-Methoden wie request nicht verwendet werden.

Shiva Kumar
quelle