tutorial rails factorybot example bot ruby-on-rails factory-bot

ruby on rails - rails - ¿Por qué factory_girl no funciona transaccionalmente para mí?-las filas permanecen en la base de datos después de las pruebas



rspec factory bot (5)

Dentro de test/test_helper.rb asegúrese de tener lo siguiente.

class ActiveSupport::TestCase self.use_transactional_fixtures = true #... end

A pesar del nombre "accesorios" esto funciona también con factory_girl .

Estoy intentando usar factory_girl para crear una fábrica de "usuario" (con RSpec), pero parece que no funciona de manera transaccional y aparentemente está fallando debido a los datos remanentes de pruebas anteriores en la base de datos de prueba.

Factory.define :user do |user| user.name "Joe Blow" user.email "[email protected]" user.password ''password'' user.password_confirmation ''password'' end @user = Factory.create(:user)

Ejecutar el primer conjunto de pruebas está bien:

spec spec/ ... Finished in 2.758806 seconds 60 examples, 0 failures, 11 pending

Todo bien y como se esperaba, sin embargo, ejecutando las pruebas nuevamente:

spec spec/ ... /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/validations.rb:1102:in `save_without_dirty!'': Validation failed: Email has already been taken (ActiveRecord::RecordInvalid) from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/dirty.rb:87:in `save_without_transactions!'' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:200:in `save!'' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction'' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:182:in `transaction'' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:200:in `save!'' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:208:in `rollback_active_record_state!'' from /Library/Ruby/Gems/1.8/gems/activerecord-2.3.8/lib/active_record/transactions.rb:200:in `save!'' from /Library/Ruby/Gems/1.8/gems/factory_girl-1.2.3/lib/factory_girl/proxy/create.rb:6:in `result'' from /Library/Ruby/Gems/1.8/gems/factory_girl-1.2.3/lib/factory_girl/factory.rb:316:in `run'' from /Library/Ruby/Gems/1.8/gems/factory_girl-1.2.3/lib/factory_girl/factory.rb:260:in `create'' from /Users/petenixey/Rails_apps/resample/spec/controllers/users_controller_spec.rb:7 from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/example/example_group_methods.rb:183:in `module_eval'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/example/example_group_methods.rb:183:in `subclass'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/example/example_group_methods.rb:55:in `describe'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/example/example_group_factory.rb:31:in `create_example_group'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/dsl/main.rb:28:in `describe'' from /Users/petenixey/Rails_apps/resample/spec/controllers/users_controller_spec.rb:3 from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:147:in `load_without_new_constant_marking'' from /Library/Ruby/Gems/1.8/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:147:in `load'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:15:in `load_files'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:14:in `each'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/example_group_runner.rb:14:in `load_files'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/options.rb:133:in `run_examples'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/lib/spec/runner/command_line.rb:9:in `run'' from /Library/Ruby/Gems/1.8/gems/rspec-1.3.0/bin/spec:5 from /usr/bin/spec:19:in `load'' from /usr/bin/spec:19

Arreglo de intento - use Factory.sequence

Como tengo una restricción de exclusividad en mi campo de correo electrónico, intenté solucionar el problema utilizando el método de secuencia de factory_girl:

Factory.define :user do |user| user.name "Joe Blow" user.sequence(:email) {|n| "joe#{n}@blow.com" } user.password ''password'' user.password_confirmation ''password'' end

Entonces corrí

rake db:test:prepare spec spec/ .. # running the tests once executes fine spec spec/ .. # running them the second time produces the same set of errors as before

Los usuarios parecen permanecer en la base de datos

Si miro la base de datos /db/test.sqlite3, parece que la fila para el usuario de prueba no se está retirando de la base de datos entre las pruebas. Pensé que se suponía que estas pruebas serían transaccionales, pero no parecen ser así para mí.

Esto explicaría por qué la prueba se ejecuta correctamente la primera vez (y si borro la base de datos) pero falla la segunda vez.

¿Alguien puede explicar lo que debería cambiar para garantizar que las pruebas se realicen de forma transaccional?


En spec/spec_helper.rb , asegúrese de tener lo siguiente

RSpec.configure do |config| config.use_transactional_fixtures = true end

Esto parece resolver el problema para mí.


Finalmente arreglé esto y espero poder salvar a alguien de las seis horas de depuración que me llevó a resolverlo.

Por a) tener suerte y terminar con una versión de código que funcionó yb) eliminar ambos conjuntos de códigos esto es lo que encontré:

Prueba que se ahoga

require ''spec_helper'' describe UsersController do @user = Factory.create(:user) end

Prueba que funciona

require ''spec_helper'' describe UsersController do it "should make a factory models without choking" do @user = Factory.create(:user) end end

La transacción se define por la declaración "should do something" do ... Si instancia la fábrica fuera de esa declaración, resulta que no es transaccional.

También puede colocarlo fuera del bloque "should should ..." siempre que esté en un bloque "before..end"

require ''spec_helper'' describe UsersController do before(:each) do @user = Factory.create(:user) end it ''should make a factory without choking'' do puts @user.name # prints out the correnct name for the user end end

Al experimentar, parece ser válido definir un usuario fuera de un bloque "debería hacer ... fin" siempre que esté en un bloque "antes ... fin". Supongo que esto solo se ejecuta en el alcance del bloque "debería hacer ... fin" y, por lo tanto, funciona bien.

[Gracias a @jdl por su sugerencia (también correcta)]


Me encontré con los mismos síntomas cuando actualicé un proyecto de Rails 3 a Rails 4. Hice una instalación de paquete, y el modo de desarrollo parecía funcionar bien, pero no obtuve el comportamiento transaccional en las pruebas. Resulta que al hacer una actualización del paquete, se solucionó el problema.