IIC3745-2020-2/syllabus

Error con factory bot al correr los test

Closed this issue · 4 comments

Hola!
Sucede que los test estaban corriendo bien, y probando algunas cosas creo que me eché algo 😬 y ahora me sale este error:

Failure/Error: @user = FactoryBot.create( :user )
     ActiveRecord::RecordInvalid:
       Validation failed: Email has already been taken

Pero, estamos usando el siguiente código para la factory:

FactoryBot.define do
  # Para atributos que no se pueden repetir
  sequence :email do |n|
    "person#{n}@walletest.cl"
  end

  # Uso: FactoryBot.create( :user, traits: [:admin] )
  factory :user do
    trait :admin do
      is_admin { true }
    end
    name { 'Name' }
    lastname { 'LastName' }
    rut { '11.111.111-1' }
    email { generate :email }
    password { 'aaaaaa' }
  end
end

Y obviamente antes corrí mil veces los test y todo funcionaba bien y después algo debo haber hecho que dejó de funcionar, volví al código atrás cuando todo funcionaba y me sigue tirando el error.

Busqué el error en google, pero hablan quizás de una gema para limpiar la bd, pero no sé si es lo correcto.

Ayuda por favor 😢

Hola,

Pienso que el problema puede ser la notación que usas para generar la secuencia de email (porque nunca había visto esa notación). Ve si usando la secuencia directamente dentro de la factory de user (como en este ejemplo) se soluciona tu problema.

De no ser así, entonces puede ser un problema con los datos de pruebas. Como comentas, una opción es que no se esté limpiando correctamente la base de datos después de cada test. Pienso que la forma más fácil de comprobar este supuesto es borrando la base de datos de pruebas completamente y creandola nuevamente, con rails db:drop y rails db:create db:schema:load (tienes que especificar RAILS_ENV=test si no quieres perder los datos de development). Luego, tienes que correr solamente el test que falla (para evitar que otros tests poblen la base de datos que podría tener problemas de limpieza), y si este aprueba, entonces el problema es lo que comentas.

Otra opción es que para el test que te falla crees "a mano" el mismo usuario con correo duplicado. Esto puede estar oculto a través de before anidados. Sin embargo esta opción es extraña porque si estás haciendo checkout a un commit que antes funcionaba no debería ser este el problema.

Una última opción que se me ocurre es que estés usando la funcionalidad de fixtures de RoR. No he mencionado este concepto en clases pero resumidamente los datos que se crean a través de esta forma se definen como el "estado inicial" para cada test: luego de que se ejecute cada test se hace rollback a los datos que se definieron en las fixtures. La idea de esto es ganar tiempo al ejecutar los tests porque los datos definidos en las fixtures se crean una sola al inicio, y entre tests se realiza un rollback solamente, lo que es más rápido que crear y borrar registros en la base de datos entre cada test. Por lo tanto, si es que en las fixtures definiste un usuario, y luego en los tests tratas de crearlo nuevamente entonces fallará por correo duplicado.

También puedes probar si un compañero tuyo de grupo también tiene este error al ejecutar los tests. De esta forma podrás ver si el problema es por una configuración de tu computador o un error de la aplicación.

Cuéntame si alguna de estas opciones te encamina a solucionar el problema. De lo contrario tendrías que entregar más detalle como el test en particular que te falla en qué commit, y un commit en que estés completamente segura que funcionaba, para así poder comparar todos los cambios que se hicieron entremedio y ver si hay alguna explicación a nivel de código.

Buenísima! Gracias, me sirvió dropear la bd, algún condoro me debo haber mandado. Igual, para entender un poco mejor como funciona esto, cada vez que corro todos los test se agregan entradas a la bd? Y eso no se borra a menos que la dropee manualmente?

Depende como configures tu ambiente de pruebas qué pasará con los datos entre cada test. Por ejemplo, RSpec por defecto configura que cada test se ejecute dentro de una transacción, para que así las modificaciones a los datos entre tests sean independientes. En esta sección de la documentación de RSpec puedes leer más sobre esto.

Por otra parte, Cucumber no tiene una política incluida para esto, por lo que recomiendan incluir database_cleaner al instalar la gema en RoR.

Sospecho que tu problema se debía a que la base de datos de tests tenía datos antes de que ejecutaras los tests (quizás los agregaste sin darte cuenta), por lo que estos no se borraban entre las ejecuciones de los tests.

Buena! Muchas gracias