рейки rspec перед усіма проти перед кожним


79

competition_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

Коли я запускаю ці тести, все в порядку, але якщо я заміню перед (: all) на before (: each), кожен тест буде невдалим. Я не знаю, чому це відбувається?

У цьому полягає помилка

 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

Відповіді:


120

before(:all) запускає блок один раз перед запуском усіх прикладів.

before(:each) запускає блок один раз перед кожною із специфікацій у файлі

before(:all)встановлює змінні екземпляра @admission, @project, @creative, @contest_entryодин раз до itзапуску всіх блоків.

Однак :before(:each)скидає змінні екземпляра в блоці before кожен раз, коли itзапускається блок.

Це тонка відмінність, але важлива

знову,

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) }

ви знаєте , чому він не зміг , хоча з до (: кожен)
Sethi

38

Важливою деталлю before :allє те, що це не БД transactional. Тобто, все, що before :allзберігається в БД, зберігається в БД, і ви повинні вручну зруйнувати файлafter :all метод.

Наслідки означають, що після завершення тестових наборів зміни не повертаються до наступних тестів. Це може спричинити складні помилки та проблеми із перехресним забрудненням даних. Тобто, якщо видається виняток, after :allзворотний виклик не викликається.

Однак, before: each це транзакція БД.

Швидкий тест для демонстрації:

1. Зріжте відповідну таблицю БД, а потім спробуйте це,

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

2. Спостерігайте за базою даних, після чого модель залишається збереженою !

after :allнеобхідно. Однак, якщо у вашому тесті трапляється виняток, цей зворотний виклик не відбуватиметься, оскільки потік був перерваний. База даних залишатиметься у невідомому стані, що може бути особливо проблематичним для середовищ CI / CD та автоматизованого тестування.

3. зараз спробуйте це,

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

4. Тепер база даних залишається позбавленою даних після завершення набору тестів. Набагато краще і залишає нам стабільний стан після запуску тестів.

Коротше кажучи, before :eachце, мабуть, те, що ви хочете. Ваші тести працюватимуть трохи повільніше, але це варто витратити.

Детально тут: https://relishapp.com/rspec/rspec-rails/docs/transactions Див .:Data created in before(:all) are not rolled back

Сподіваюся, це допоможе іншому втомленому мандрівнику


Ці поради рятують мій день! Просто напишіть до до ((кожен)
Гумберто Коррея,

4

before(:all), що гарантує, що вибіркові користувачі створюються один раз перед усіма тестами в блоці. Це оптимізація швидкості.


0

Одне слід зазначити за замовчуванням перед використанням перед (: кожним), а також перед ((всі)) екземпляром контролера не встановлено, тому методи контролера, такі як запит, не використовуються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.