ruby-on-rails - rails - visual studio code mark tags
Rspec rieles antes de todos vs antes de cada (3)
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
Cuando realizo estas pruebas, todo está bien, pero si cambio antes (: todos) a antes (cada uno), fallarán todas las pruebas. ¿No sé por qué sucede?
Este es el error
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
Uno de los detalles más importantes de before :all
es que no es DB transactional
. Es decir, cualquier cosa dentro de la before :all
persiste en la base de datos y debe eliminar manualmente en el método after :all
. Las implicaciones significan que, después de que los conjuntos de pruebas se hayan completado, los cambios no se revierten listos para las próximas pruebas. Esto puede provocar errores y problemas complicados con la contaminación cruzada de datos entre pruebas. Recuerde, si se lanza una excepción after :all
no se llama a after :all
devolución de llamada.
Una prueba rápida para demostrar:
1. Truncar la tabla de DB adecuada y luego probar esto,
before :all do
@user = Fabricate(:user, name: ''Happy Fun Pants'')
end
2. Observe la base de datos después, ¡notará que el modelo permanece persistente ! Esto se debe a que debe incluir after :all
, pero de nuevo, si se produce una excepción en su prueba, esta devolución de llamada no se producirá. Cualquier prueba futura se ejecutará ahora contra un estado DB incierto.
3. Ahora intenta esto,
before :each do
@user = Fabricate(:user, name: ''Happy Fun Pants'')
end
4. Ahora la base de datos permanece desprovista de datos una vez que se completa el conjunto de pruebas. No es bueno con las configuraciones de CI / CD.
Pueden surgir errores complicados si una prueba arroja una excepción y no se completa entre los 100 (impidiendo que se complete todo el conjunto de pruebas). La base de datos se dejará en un estado desconocido.
En resumen, before :each
, es probablemente lo que quieres. Sus pruebas se ejecutarán un poco más lento, pero deberían valer la pena.
Detalle aquí: https://relishapp.com/rspec/rspec-rails/docs/transactions Consulte: Los Data created in before(:all) are not rolled back
Espero que ayude a otro viajero cansado.
before(:all)
, que garantiza que los usuarios de muestra se crean una vez, antes de todas las pruebas en el bloque. Esta es una optimización para la velocidad.
before(:all)
ejecuta el bloque una vez antes de ejecutar todos los ejemplos.
before(:each)
ejecuta el bloque una vez antes de cada una de sus especificaciones en el archivo
before(:all)
establece las variables de instancia @admission, @project, @creative, @contest_entry
una vez antes de it
se ejecuten todos it
bloques.
Sin embargo :before(:each)
restablece las variables de instancia en el bloque before cada vez it
se ejecuta un bloque it
.
Es una distinción sutil pero importante
de nuevo,
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) }