¿Cómo preparo la(s) base (s) de pruebas para las pruebas Rails rspec sin ejecutar rake spec?


Después de solucionar problemas significativos, me di cuenta de que necesitaba ejecutar rake spec una vez (puedo abortar con control-c) antes de poder ejecutar rspec directamente (por ejemplo, en un subconjunto de nuestras especificaciones). Estamos ejecutando Rails 3.0.7 y RSpec 2.5.0.

Claramente, rake está ejecutando algunas tareas / código importantes de configuración de la base de datos (tenemos código personalizado en el rails Rakefile de nivel raíz y posiblemente en otros lugares).

¿Cómo puedo ejecutar las tareas / código de configuración de la base de datos de prueba de rake sin ejecutar rake spec?

Además de poder ejecutar rspec en un subconjunto de archivos, estoy usando specjour para difundir nuestras especificaciones a través de múltiples núcleos (no he tenido éxito con la difusión a través de la LAN todavía), pero veo el mismo comportamiento que para ejecutar rspec directamente: Necesito ejecutar rake spec en cada base de datos de prueba (suponiendo dos núcleos) antes de que specjour funcione:

rake spec TEST_ENV_NUMBER=1
control-c (after tests start)
rake spec TEST_ENV_NUMBER=2
control-c (after tests start)
specjour

Nota: mi configuración/base de datos.yml tiene esta entrada para la prueba (como es común para la prueba paralela gemas):

test:
  adapter: postgresql
  encoding: unicode
  database: test<%=ENV['TEST_ENV_NUMBER']%>
  username: user
  password:

Parallel_tests parece configurar sus bases de datos correctamente, pero muchas de nuestras especificaciones fallan.

También debo mencionar que ejecutar specjour prepare hace que Postgres registre errores que no puede encontrar las bases de datos, pero las crea (sin tablas). En una ejecución posterior, no se registran errores, pero tampoco se crean tablas. Es posible que todo mi problema sea simplemente un error en prepare, así que lo reporté en github.

Creo que puedo ejecutar código arbitrario en cada base de datos de pruebas specjour configurando Specjour::Configuration.prepare in.specjour / hooks.rb, así que si hay alguna tarea de rake u otro código que necesito ejecutar, puede funcionar allí.

Author: gerry3, 2011-05-06

5 answers

Tuve un problema similar al configurar el sistema de CI en el trabajo, así que gradualmente desarrollé un sistema para manejar esto. Puede que no sea la mejor solución, pero funciona para mí en mi situación y siempre estoy buscando mejores formas de hacer las cosas.

Tengo una base de datos de pruebas que necesitaba configurar, pero también necesitaba datos sembrados cargados para que nuestras pruebas funcionen.

Lo básico para solucionar las tareas de rake es ejecutar rake con la opción trace trace para ver lo que está sucediendo debajo del capó. Cuando yo al hacer esto, descubrí que ejecutar rake spec hizo una serie de cosas que podía replicar (o modificar según lo considerara conveniente) en una tarea de rake personalizada.

Aquí hay un ejemplo de lo que hacemos.

desc "Setup test database - drops, loads schema, migrates and seeds the test db"
task :test_db_setup => [:pre_reqs] do
  Rails.env = ENV['RAILS_ENV'] = 'test'
  Rake::Task['db:drop'].invoke
  Rake::Task['db:create'].invoke
  result = capture_stdout { Rake::Task['db:schema:load'].invoke }
  File.open(File.join(ENV['CC_BUILD_ARTIFACTS'] || 'log', 'schema-load.log'), 'w') { |f| f.write(result) }
  Rake::Task['db:seed:load'].invoke
  ActiveRecord::Base.establish_connection
  Rake::Task['db:migrate'].invoke
end

Esto es solo un ejemplo, y específico para nuestra situación, por lo que tendrá que averiguar lo que hay que hacer para obtener la configuración de la base de datos de prueba, pero es bastante fácil de determinar utilizando la opción trace trace de rake.

Además, si encuentra que la configuración de la prueba está tomando demasiado tiempo (como lo hace en nuestro caso), también puede volcar la base de datos en .formato sql y hacer que la base de datos de prueba lo canalice directamente a mysql para cargarlo. Ahorramos varios minutos de la configuración de la base de datos de prueba de esa manera. No muestro eso aquí porque complica las cosas sustancialmente needs necesita ser generado correctamente sin quedar rancio, etc.

HTH

 13
Author: edk750,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-07 16:55:00

Recomendaría dejar caer su base de datos de prueba, luego volver a crearla y migrar:

bundle exec rake db:drop RAILS_ENV=test
bundle exec rake db:create RAILS_ENV=test
bundle exec rake db:schema:load RAILS_ENV=test

Después de estos pasos, puede ejecutar sus especificaciones:

bundle exec rspec spec

Gerry3 señaló que:

Una solución más simple es simplemente ejecutar rake db:test:prepare

Sin embargo, si está usando PostgreSQL esto no funcionará porque el entorno rails se carga, lo que abre una conexión a la base de datos. Esto hace que la llamada prepare falle, porque la base de datos no se puede eliminar. Algo complicado.

 139
Author: leviathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:33:14

Todas las soluciones proporcionadas requieren cargar el entorno Rails, que en la mayoría de los casos no es el comportamiento deseado debido a una sobrecarga muy grande y una velocidad muy baja. DatabaseCleaner la gema también es bastante lenta, y agrega otra dependencia a tu aplicación.

Después de meses de disgusto y disgusto gracias a razones como la anterior, finalmente he encontrado la siguiente solución para ser exactamente lo que necesito. Es agradable, simple y rápido. En spec_helper.rb:

config.after :all do
  ActiveRecord::Base.subclasses.each(&:delete_all)
end

La mejor parte de esto es: Solo borra las tablas que efectivamente has tocado (los modelos intactos no se cargarán y por lo tanto no aparecerán en subclasses, también la razón por la que esto no funciona antes de las pruebas). Además, se ejecuta después de las pruebas, por lo que los puntos verdes (con suerte) aparecerán de inmediato.

El único inconveniente de esto es que si tiene una base de datos sucia antes de ejecutar pruebas, no se limpiará. Pero dudo que sea un problema importante, ya que la base de datos de prueba generalmente no se toca de pruebas externas.

Editar

Dado que esta respuesta ha ganado cierta popularidad, quería editarla para completarla: si desea borrar todas las tablas, incluso las que no se tocan, debería poder hacer algo como los "hacks" a continuación.

Hack 1-pre-carga de todos los modelos para subclasses método

Evalúe esto antes de llamar subclasses:

Dir[Rails.root.join("app", "models", "**", "*.rb")].each(&method(:require))

Tenga en cuenta que este método puede tomar algún tiempo!

Hack 2-truncando manualmente el cuadros

ActiveRecord::Base.connection.tables.keep_if{ |x| x != 'schema_migrations' }

Te dará todos los nombres de tabla, con los que puedes hacer algo como:

case ActiveRecord::Base.configurations[Rails.env]["adapter"]
when /^mysql/, /^postgresql/
  ActiveRecord::Base.connection.execute("TRUNCATE #{table_name}")
when /^sqlite/
  ActiveRecord::Base.connection.execute("DELETE FROM #{table_name}")
  ActiveRecord::Base.connection.execute("DELETE FROM sqlite_sequence where name='#{table_name}'")
end
 14
Author: Danyel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-31 14:55:25

Parece que en Rails 4.1+, la mejor solución es simplemente agregar ActiveRecord::Migration.maintain_test_schema! en su rails_helper después de require 'rspec/rails'.

Es decir, ya no tiene que preocuparse por tener que preparar la base de datos.

Https://relishapp.com/rspec/rspec-rails/docs/upgrade#pending-migration-checks

 5
Author: John Morales,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-02 23:02:08

En una aplicación Rails 4 reforzada con resorte, my bin/setup generalmente se aumenta para contener

puts "\n== Preparing test database =="
system "RAILS_ENV=test bin/rake db:setup"

Esto es muy similar a la respuesta de leviathan , además de sembrar la DB de prueba, como

rake db:setup # Cree la base de datos, cargue el esquema e inicialice con los datos semilla
(uso
db:reset para eliminar también la base de datos primero)

Como menciona el comentario, si queremos eliminar la base de datos primero, rake db:reset hace precisamente eso.

También encuentro que esto proporciona más retroalimentación en comparación con rake db:test:prepare.

 3
Author: Marius Butuc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:33:14