La gente parece haber explicado algunas de las formas básicas en las que se diferencian, pero no before(:all)
y no explican exactamente por qué deberían usarse.
Creo que las variables de instancia no tienen lugar en la gran mayoría de las especificaciones, en parte debido a las razones mencionadas en esta respuesta , por lo que no las mencionaré como una opción aquí.
dejar bloques
Código dentro de un let
bloque solo se ejecuta cuando se hace referencia, la carga diferida significa que el orden de estos bloques es irrelevante. Esto le brinda una gran cantidad de energía para reducir la configuración repetida a través de sus especificaciones.
Un ejemplo (extremadamente pequeño y artificial) de esto es:
let(:person) { build(:person) }
subject(:result) { Library.calculate_awesome(person, has_moustache) }
context 'with a moustache' do
let(:has_moustache) { true }
its(:awesome?) { should be_true }
end
context 'without a moustache' do
let(:has_moustache) { false }
its(:awesome?) { should be_false }
end
Puede ver que has_moustache
se define de manera diferente en cada caso, pero no es necesario repetir la subject
definición. Algo importante a tener en cuenta es que let
se utilizará el último bloque definido en el contexto actual. Esto es bueno para establecer un valor predeterminado que se utilizará para la mayoría de las especificaciones, que se pueden sobrescribir si es necesario.
Por ejemplo, verificar el valor de retorno de calculate_awesome
si se pasa un person
modelo con el top_hat
valor verdadero, pero sin bigote sería:
context 'without a moustache but with a top hat' do
let(:has_moustache) { false }
let(:person) { build(:person, top_hat: true) }
its(:awesome?) { should be_true }
end
Otra cosa a tener en cuenta sobre los bloques let, no deben usarse si está buscando algo que se ha guardado en la base de datos (es decir Library.find_awesome_people(search_criteria)
), ya que no se guardarán en la base de datos a menos que ya se haya hecho referencia a ellos. let!
o before
bloques son los que deberían usarse aquí.
Además, nunca lo utilice before
para activar la ejecución de let
bloques, ¡para esto let!
está hecho!
¡dejar! bloques
let!
los bloques se ejecutan en el orden en que están definidos (muy parecido a un bloque anterior). La única diferencia fundamental con los bloques before es que obtiene una referencia explícita a esta variable, en lugar de tener que recurrir a las variables de instancia.
Al igual que con los let
bloques, si let!
se definen varios bloques con el mismo nombre, el más reciente es el que se utilizará en la ejecución. La diferencia principal es que los let!
bloques se ejecutarán varias veces si se usan así, mientras que el let
bloque solo se ejecutará la última vez.
antes (: cada) bloques
before(:each)
es el bloque anterior predeterminado y, por lo tanto, se puede hacer referencia a él en before {}
lugar de especificar el completo before(:each) {}
cada vez.
Es mi preferencia personal usar before
bloques en algunas situaciones básicas. Usaré antes de los bloques si:
- Estoy usando burla, stubbing o dobles
- Existe una configuración de tamaño razonable (generalmente, esto es una señal de que sus rasgos de fábrica no se han configurado correctamente)
- Hay una serie de variables a las que no necesito hacer referencia directamente, pero son necesarias para la configuración
- Estoy escribiendo pruebas de controlador funcional en rieles y quiero ejecutar una solicitud específica para probar (es decir
before { get :index }
). Aunque podría usar subject
para esto en muchos casos, a veces se siente más explícito si no necesita una referencia.
Si se encuentra escribiendo before
bloques grandes para sus especificaciones, revise sus fábricas y asegúrese de comprender completamente los rasgos y su flexibilidad.
antes (: todos) bloques
Estos solo se ejecutan una vez, antes de las especificaciones en el contexto actual (y sus hijos). Estos se pueden utilizar con gran ventaja si se escriben correctamente, ya que hay ciertas situaciones que pueden reducir la ejecución y el esfuerzo.
Un ejemplo (que difícilmente afectaría el tiempo de ejecución) es simular una variable ENV para una prueba, que solo debería tener que hacer una vez.
Espero que ayude :)