96 votes

Rspec - Différence entre les blocs let et before

Quelle est la difference entre let et before block in rspec?

Et quand utiliser ces blocs?

Quelle sera la bonne approche laisser ou avant dans l'exemple ci-dessous

 let(:user) { User.make !}
let(:account) {user.account.make!}

before(:each) do
 @user = User.make!
 @account = @user.account.make!
end
 

J'ai étudié ce post stackoverflow

Mais est-il bon de définir laisser pour les choses d'association comme ci-dessus?

159voto

Jay Points 1450

Les gens semblent avoir expliqué certaines des méthodes de base dans lesquelles ils diffèrent, mais laissé de côté avant(:all) et de ne pas expliquer exactement pourquoi ils devraient être utilisés.

C'est ma conviction que les variables d'instance ont pas lieu d'être utilisé dans la grande majorité des specs, en partie à cause des raisons évoquées au début de cet article http://bitfluxx.com/2011/05/23/some-rspec-tips-and-best-practices.html, donc je n'en parle pas comme une option ici.

laissez-blocs

Code à l'intérieur d'un let bloc est exécuté seulement si elle est référencée, le chargement paresseux cela signifie que la commande de ces blocs n'est pas pertinent. Cela vous donne une grande quantité de puissance pour couper vers le bas sur répétées de l'installation par le biais de vos spécifications.

Un (très artificiel, et petit) exemple de cela est la suivante:

let(:person)     { build(:person) }
subject(:result) { Library.calculate_awesome(person, has_moustache) }

context 'with a moustache' do
  let(:has_moustache) { true } 
  its(:is_awesome?)   { should be_true }
end

context 'without a moustache' do
  let(:has_moustache) { false } 
  its(:is_awesome?)   { should be_false }
end

Quelque chose à noter est que la dernière let bloc défini dans le contexte actuel sera utilisé. C'est bon pour le paramètre par défaut pour être utilisé pour la majorité des spécifications, qui peuvent être remplacées si nécessaire.

Par exemple, la vérification de la valeur de retour de l' calculate_awesome si passé un person modèle top_hat la valeur true, mais pas de moustache serait fait comme:

context 'with no moustache but with a top hat' do
  let(:has_moustache) { false } 
  let(:person)        { build(:person, top_hat: true) }
  its(:is_awesome?)   { should be_true }
end

Une autre chose à noter à propos de laisser les blocs, c'est qu'ils ne doivent pas être utilisés si vous êtes à la recherche de quelque chose qui a été enregistré dans la base de données (c - Library.find_awesome_people(search_criteria)) qu'ils ne seront pas enregistrées dans la base de données, sauf si elles ont déjà été citées. let! ou before des blocs sont ce qui doit être utilisé ici.

Aussi, ne jamais jamais utiliser before pour déclencher l'exécution d' let blocs, c'est ce qu' let! est faite pour ça!

laissez! les blocs

let! des blocs sont exécutés dans l'ordre de l'exécution (un peu comme un avant de bloc). La différence essentielle est que vous obtenez une référence explicite à cette variable, plutôt que de les obliger à revenir à des variables d'instance.

Comme avec d' let blocs, si plusieurs let! des blocs sont définies avec le même nom, le plus récemment défini est ce qui va être utilisé dans l'exécution. La principale différence étant que l' let! blocs sera exécutée plusieurs fois si utilisé comme cela, alors que l' let bloc n'exécutera la dernière fois.

before(:each) blocs

before(:each) est la valeur par défaut avant de bloc, et peut donc être référencé en tant que before {} plutôt que de spécifier le plein before(:each) {} à chaque fois.

C'est ma préférence personnelle pour utiliser before de blocs dans une base de situations. Je vais utiliser avant que les blocs si:

  • Je suis l'aide de moqueries, cogner ou double
  • Il est raisonnable de la taille de l'installation (en général c'est un signe que votre usine traits n'ont pas été configuré correctement)
  • Il y a un certain nombre de variables qui je n'ai pas besoin de faire référence directement, mais sont requis pour l'installation
  • Je suis en train d'écrire fonctionnelle contrôleur de tests dans les rails, et je veux exécuter une requête à l'essai (c - before { get :index }). Même si vous pouvez utiliser subject dans beaucoup de cas, il se sent parfois plus explicite si vous n'avez pas besoin d'une référence.

Si vous vous trouvez l'écriture d'un vaste before blocs pour vos specs, vérifiez vos usines et assurez-vous de bien comprendre les traits et leur flexibilité.

avant(:all) blocs

Ces ne sont jamais exécutées une fois, avant les specs, dans le contexte actuel (et ses enfants). Elles peuvent être utilisées pour grand avantage s'il est écrit correctement, comme il y a certaines situations, cela peut couper vers le bas sur l'exécution et de l'effort.

Un exemple (qui ne serait guère influer sur le temps d'exécution, en se moquant d'un ENV variable pour un test, qui vous ne devriez jamais avoir besoin de le faire une fois.

Espérons que cela aide :)

26voto

Spyros Points 13741

Presque toujours, je préfère let. Le poste que vous lien indique qu' let est également plus rapide. Toutefois, à certains moments, lorsque de nombreuses commandes doivent être exécutées, j'ai pu utiliser before(:each) car sa syntaxe est plus clair lorsque plusieurs commandes sont impliqués.

Dans votre exemple, je serais certainement préfèrent utiliser let au lieu de before(:each). En général, lorsque seulement quelques-initialisation d'une variable est fait, j'ai tendance à aimer l'aide d' let.

17voto

mikeweber Points 249

Une grande différence qui n'a pas été mentionné, c'est que les variables définies avec let n'obtenez pas instancié jusqu'à ce que vous appelez pour la première fois. Ainsi pendant qu'un before(:each) bloc instancier toutes les variables, let vous permet de définir un certain nombre de variables que vous pouvez utiliser sur plusieurs tests, il n'est pas automatiquement les instancier. Sans savoir cela, vos tests peuvent revenir à mordre-vous si vous vous attendez à toutes les données à charger à l'avance. Dans certains cas, vous pouvez même définir un certain nombre de let variables, puis d'utiliser un before(:each) bloc d'appeler chaque let exemple juste pour s'assurer que les données sont disponibles pour commencer.

3voto

Tim Connor Points 21

On dirait que vous utilisez machiniste. Attention, vous pouvez voir quelques problèmes avec la marque ! à l’intérieur de laisser (la version non-bang) qui passe en dehors de la transaction globale de l’appareil (si vous utilisez des luminaires transactionnelles ainsi) donc altérer les données pour vos autres tests.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X