RSpec: Quelle est la différence entre la location et un avant de bloc?
Quelle est la différence entre let
et un before
bloc dans RSpec?
Et quand utiliser chaque?
Ce sera une bonne approche (let 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é cette stackoverflow post
Mais est-il bon de préciser que pour l'association des trucs comme ci-dessus?
- Fondamentalement, " let " est utilisé par des gens qui n'aiment pas les variables d'instance. Comme une note de côté, vous devriez envisager d'utiliser FactoryGirl ou un outil similaire.
Vous devez vous connecter pour publier un commentaire.
De gens semblent avoir expliqué certaines des méthodes de base dans lesquelles ils diffèrent, mais a laissé
before(: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 spécifications, en partie pour les raisons mentionnées dans cette réponse, donc je n'en parle pas comme une option ici.
laisser 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 petit et artificiel) exemple de ceci est:
Vous pouvez voir que
has_moustache
est défini différemment dans chaque cas, mais il n'y a pas besoin de répéter lessubject
définition. Quelque chose d'important à noter est que la dernièrelet
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
calculate_awesome
si passé unperson
modèle avectop_hat
défini à true, mais pas de moustache serait:Une autre chose à noter à propos de laisser les blocs, 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'est à dire
Library.find_awesome_people(search_criteria)
) car ils ne seront pas enregistrées dans la base de données, sauf si elles ont déjà été citées.let!
oubefore
blocs sont ce qui doit être utilisé ici.Aussi, jamais jamais utilisation
before
pour déclencher l'exécution delet
blocs, c'est ce quelet!
est faite pour ça!laisser! les blocs
let!
blocs sont exécutés dans l'ordre qu'ils sont définis (un peu comme un avant de bloc). La différence essentielle avant de blocs est que vous obtenez une référence explicite à cette variable, plutôt que de les obliger à revenir à des variables d'instance.Comme avec
let
blocs, si plusieurslet!
blocs sont définies avec le même nom, la plus récente est ce qui va être utilisé dans l'exécution. La principale différence étant quelet!
blocs sera exécutée plusieurs fois si utilisé comme cela, alors que lalet
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 quebefore {}
plutôt que de spécifier le pleinbefore(:each) {}
à chaque fois.C'est ma préférence personnelle pour l'utilisation
before
de blocs dans une base de situations. Je vais utiliser avant que les blocs si:before { get :index }
). Même si vous pouvez utilisersubject
pour cela, 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ère que cela aide 🙂
before(:all)
l'option n'existe pas dans Minitest. Voici quelques solution de contournement dans les commentaires: github.com/seattlerb/minitest/issues/61its
n'est plus dans rspec-core. Plus moderne, idiomatiques façon estit { is_expected.to be_awesome }
.Presque toujours, je préfère
let
. Le poste que vous lien indique quelet
est également plus rapide. Toutefois, à certains moments, lorsque de nombreuses commandes doivent être exécutées, j'ai pu utiliserbefore(: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 debefore(:each)
. En général, lorsque seulement quelques-initialisation d'une variable est fait, j'ai tendance à aimer l'aide delet
.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'unbefore(: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 delet
variables, puis d'utiliser unbefore(:each)
bloc d'appeler chaquelet
exemple juste pour s'assurer que les données sont disponibles pour commencer avec.let!
à définir des méthodes qui sont appelées avant chaque exemple. Voir RSpec docs.On dirait que vous êtes à l'aide de Machiniste. Méfiez-vous, vous pouvez voir quelques problèmes avec les de faire! à l'intérieur de let (le non-bang version) passe à l'extérieur de la global luminaire de la transaction (si vous utilisez transactionnelle luminaires ainsi) afin de corrompre les données pour d'autres tests.