tests test_helper test run rails how ruby-on-rails unit-testing rspec

ruby-on-rails - test_helper - rspec rails



RSpec: ¿Cuál es la diferencia entre let y a before block? (4)

¿Cuál es la diferencia entre let y a before block en RSpec?

¿Y cuándo usar cada uno?

¿Cuál será el buen enfoque (let o before) en el siguiente ejemplo?

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

Estudié esta publicación stackoverflow

Pero, ¿es bueno definir las cosas de let for association como arriba?


Casi siempre, prefiero let . La publicación que enlazas especifica que let también es más rápido. Sin embargo, a veces, cuando tienen que ejecutarse muchos comandos, podría usar before(:each) porque su sintaxis es más clara cuando hay muchos comandos involucrados.

En su ejemplo, definitivamente preferiría usar let lugar de before(:each) . En términos generales, cuando se realiza una inicialización variable, me suele gustar usar let .


La gente parece haber explicado algunas de las formas básicas en que difieren, pero las omitió 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é aquí.

dejar bloques

El código dentro de un bloque let solo se ejecuta cuando se hace referencia, la carga lenta significa que el orden de estos bloques es irrelevante. Esto le da una gran cantidad de potencia para reducir la configuración repetida a través de sus especificaciones.

Un ejemplo (extremadamente pequeño y artificioso) 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 definición del subject . Algo importante a tener en cuenta es que se usará el último bloque let 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, verificando el valor de retorno de calculate_awesome si pasa un modelo de person con top_hat establecido en verdadero, pero no 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 acerca de dejar bloques, no deberían usarse si estás buscando algo que se haya 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 hayan sido referenciado let! o before bloques son lo que se debe utilizar aquí.

Además, nunca lo use before para activar la ejecución de los bloques de let , esto es lo que let! está hecho para!

¡dejar! bloques

let! los bloques se ejecutan en el orden en que se definen (muy parecido a un bloque anterior). La única diferencia de núcleo a los bloques anteriores es que obtienes una referencia explícita a esta variable, en lugar de recurrir a variables de instancia.

Al igual que con los bloques de let , si múltiples let! los bloques se definen con el mismo nombre, el más reciente es el que se usará en la ejecución. La diferencia principal es que let! los bloques se ejecutarán varias veces si se usan así, mientras que el bloque de let solo se ejecutará la última vez.

antes (: cada) bloques

before(:each) es el bloque default before, y por lo tanto se puede referenciar como before {} lugar de especificar el full before(:each) {} cada vez.

Es mi preferencia personal utilizar bloques before en algunas situaciones centrales. Usaré antes de bloques si:

  • Estoy usando burlas, stubbing o dobles
  • Hay una configuración de tamaño razonable (en general, esto es una señal de que los rasgos de fábrica no se han configurado correctamente)
  • Hay una serie de variables a las que no necesito hacer referencia directamente, pero que 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 puede usar el subject para esto en muchos casos, a veces se siente más explícito si no necesita una referencia.

Si se encuentra escribiendo bloques grandes para sus especificaciones, verifique 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 pueden ser utilizados con gran ventaja si se escriben correctamente, ya que hay ciertas situaciones que pueden reducir la ejecución y el esfuerzo.

Un ejemplo (que apenas afectaría el tiempo de ejecución) es burlarse de una variable ENV para una prueba, que solo debería hacer una vez.

Espero que ayude :)


Parece que estás usando Machinist. ¡Cuidado, es posible que veas algunos problemas con make! dentro de let (la versión sin bang) que ocurre fuera de la transacción de fijación global (si también está utilizando dispositivos transaccionales), por lo que corrompe los datos para sus otras pruebas.


Una gran diferencia que no se ha mencionado es que las variables definidas con let no se instanciarán hasta que lo llame la primera vez. Entonces, si un bloque before(:each) instanciaría todas las variables, let a definir una cantidad de variables que podría usar en múltiples pruebas, no las creará automáticamente. Sin saber esto, sus pruebas podrían volver a morderse si espera que todos los datos se carguen de antemano. En algunos casos, es posible que desee definir un número de variables de let , luego use un bloque before(:each) para llamar a cada instancia de let solo para asegurarse de que los datos estén disponibles para comenzar.