2013-05-17 12 views
51

contest_entry_spec.rbszyny rspec przed wszystkim vs przed każdym

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 

Kiedy uruchomić te testy wszystko jest okey ale jeśli zmienię przed (: all) do wcześniej (: każdy) każda próba będzie uznany za niesprawny . Nie wiem, dlaczego tak się dzieje?

Jest to błąd

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 

Odpowiedz

85

before(:all) uruchamia jeden blok zanim prowadzone są we wszystkich przykładach.

before(:each) uruchamia jeden blok zanim każdy z twoich specyfikacji w pliku

before(:all) ustawia zmienne instancji @admission, @project, @creative, @contest_entry jeden raz przed wszystkimi it bloki są uruchamiane.

Jednak :before(:each) resetuje zmienne instancji w poprzednim bloku za każdym razem, gdy uruchamiany jest blok it.

Jej subtelna różnica, ale ważne

znowu

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

Daj mi znać, jeśli masz jakiekolwiek pytania. Cieszę się, że mogę pomóc – fontno

3

before(:all), który zapewnia, że ​​użytkownicy próbki są tworzone raz, zanim wszystkich testów w bloku. Jest to optymalizacja prędkości.

14

Jednym z najważniejszych szczegółów before :all jest to, że jest to , a nie DB transactional. Oznacza to, że wszystko w ramach before :all utrzymuje się w db i musisz ręcznie zburzyć metodę after :all. Konsekwencje oznaczają, że po zakończeniu testów zestawy zmian nie są ponownie gotowe do następnych testów. Może to spowodować skomplikowane błędy i problemy z krzyżowym zanieczyszczeniem danych między testami. Pamiętaj, że jeśli zostanie zgłoszony wyjątek, wywołanie zwrotne after :all nie zostanie wywołane.

Szybki test do wykazania:

1. Obciąć Twój odpowiedniej tabeli DB następnie spróbować tego,

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

2. przestrzegać bazy potem, można zauważyć model pozostaje trwały!? Dzieje się tak, ponieważ musisz włączyć after :all, ale ponownie, jeśli wystąpi wyjątek w twoim teście, to wywołanie zwrotne nie wystąpi! Wszelkie przyszłe testy będą teraz działać przeciwko niepewnemu stanowi DB.

3. teraz spróbować,

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

4. Teraz baza pozostaje pozbawiona danych po zestaw testów jest kompletny. Niedobrze z konfiguracjami CI/CD.

Powodowane błędy mogą powstać, jeśli test zgłasza wyjątek i nie zakończy się wśród lat 100 (uniemożliwienie ukończenia całego zestawu testów). Baza danych pozostanie w nieznanym stanie.

Krótko mówiąc, before :each, prawdopodobnie jest to, co chcesz. Twoje testy przebiegną nieco wolniej, ale powinny być tego warte.

Szczegóły tutaj: https://relishapp.com/rspec/rspec-rails/docs/transactions Patrz: Data created in before(:all) are not rolled back

nadzieję, że pomoże inny zmęczony podróżny.

+0

Te wskazówki oszczędzają mój dzień! Po prostu napisz wcześniej (przedtem): –

Powiązane problemy