rails rspec avant tout vs avant chacun

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 

Quand je lance ces tests, tout va bien mais si je passe avant (: tout) à avant (: chacun) chaque test échouera. Je ne sais pas pourquoi cela se produit?

C’est l’erreur

  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 

before(:all) exécute le bloc une fois avant que tous les exemples ne soient exécutés.

before(:each) exécute le bloc une fois avant chacune de vos spécifications dans le fichier

before(:all) définit les variables d’instance @admission, @project, @creative, @contest_entry une fois avant que tous les blocs it soient exécutés.

Cependant :before(:each) réinitialise les variables d’instance dans le bloc avant chaque exécution d’un bloc.

C’est une distinction subtile mais importante

encore,

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

Un détail important de before :all est que ce n’est pas transactional données. C’est-à-dire n’importe quoi dans l’ before :all persiste dans la firebase database et vous devez supprimer manuellement la méthode after :all .

Les implications signifient que, une fois les suites de tests terminées, les modifications ne sont pas rétablies pour les tests ultérieurs. Cela peut entraîner des bogues complexes et des problèmes de contamination croisée des données. Si une exception est levée, l’ after :all rappel n’est pas appelé.

Un test rapide pour démontrer:

1. Tronquez votre table de firebase database appropriée, puis essayez ceci,

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

2. Observez la firebase database après la fin du modèle ! after :all est requirejs. Toutefois, si une exception se produit dans votre test, ce rappel ne se produira pas tant que le stream aura été interrompu!

3. maintenant, essayez ceci,

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

4. Maintenant, la firebase database rest dépourvue de données une fois la suite de tests terminée. Pas bon avec les configurations CI / CD.

Des bugs compliqués peuvent survenir si un test déclenche une exception et ne se termine pas. La firebase database sera laissée dans un état inconnu.

En bref, before :each est probablement ce que vous voulez. Vos tests seront légèrement plus lents, mais cela en vaut la peine.

Détail ici: https://relishapp.com/rspec/rspec-rails/docs/transactions See: Data created in before(:all) are not rolled back

J’espère que ça aide un autre voyageur fatigué.

before(:all) , qui garantit que les exemples d’utilisateurs sont créés une fois, avant tous les tests du bloc. Ceci est une optimisation pour la vitesse.

Une chose à noter est par défaut avant utilisation avant (: chaque), également dans avant (: tous) l’instance du contrôleur n’est pas définie, donc les méthodes du contrôleur comme la demande ne sont pas utilisées.