Pregunta ¿Cómo pruebo las migraciones de Rails?


Quiero probar que ciertas condiciones se mantienen después de ejecutar una migración que he escrito. ¿Cuál es la mejor manera actual de hacer eso?

Para hacer esto concreto: realicé una migración que agrega una columna a un modelo y le da un valor predeterminado. Pero olvidé actualizar todas las instancias preexistentes de ese modelo para tener ese valor predeterminado para la nueva columna. Ninguna de mis pruebas actuales detectará eso, porque todas comienzan con una nueva base de datos y agregan nuevos datos, que tendrán el valor predeterminado. Pero si presiono para la producción, sé que las cosas se romperán, y quiero que mis pruebas me digan eso.

He encontrado http://spin.atomicobject.com/2007/02/27/migration-testing-in-rails/, pero no lo he probado Es muy viejo ¿Es ese el estado del arte?


48
2018-05-21 01:24


origen


Respuestas:


Peter Marklund tiene un ejemplo fundamental de probar una migración aquí: https://gist.github.com/700194 (en rspec).

Nota: las migraciones han cambiado desde su ejemplo para usar métodos de instancia en lugar de métodos de clase.

Aquí hay un resumen:

  1. Crear una migración como de costumbre
  2. Crea un archivo para poner tu prueba de migración. Sugerencias: test/unit/import_legacy_devices_migration_test.rb o spec/migrations/import_legacy_devices_migration_spec.rb NOTA: probablemente necesite cargar explícitamente el archivo de migración ya que los rieles probablemente no lo carguen por usted. Algo como esto debería hacer: require File.join(Rails.root, 'db', 'migrate', '20101110154036_import_legacy_devices')
  3. Las migraciones son (como todo en ruby), solo una clase. Prueba el up y down métodos. Si su lógica es compleja, sugiero refactorizar bits de lógica a métodos más pequeños que serán más fáciles de probar.
  4. Antes de llamar up, configure algunos datos como lo haría antes de su migración, y afirme que su estado es lo que espera después.

Espero que esto ayude.

ACTUALIZAR: Desde publicar esto, publiqué en mi blog una ejemplo de prueba de migración.

ACTUALIZAR: Aquí hay una idea para probar migraciones incluso después de que se hayan ejecutado en desarrollo.

EDITAR: He actualizado mi prueba de concepto a un archivo de especificación completo utilizando el ejemplo artificial de mi publicación de blog.

# spec/migrations/add_email_at_utc_hour_to_users_spec.rb
require 'spec_helper'

migration_file_name = Dir[Rails.root.join('db/migrate/*_add_email_at_utc_hour_to_users.rb')].first
require migration_file_name


describe AddEmailAtUtcHourToUsers do

  # This is clearly not very safe or pretty code, and there may be a
  # rails api that handles this. I am just going for a proof of concept here.
  def migration_has_been_run?(version)
    table_name = ActiveRecord::Migrator.schema_migrations_table_name
    query = "SELECT version FROM %s WHERE version = '%s'" % [table_name, version]
    ActiveRecord::Base.connection.execute(query).any?
  end

  let(:migration) { AddEmailAtUtcHourToUsers.new }


  before do
    # You could hard-code the migration number, or find it from the filename...
    if migration_has_been_run?('20120425063641')
      # If this migration has already been in our current database, run down first
      migration.down
    end
  end


  describe '#up' do
    before { migration.up; User.reset_column_information }

    it 'adds the email_at_utc_hour column' do
      User.columns_hash.should have_key('email_at_utc_hour')
    end
  end
end

15
2018-04-14 16:26



Hice una migración que agrega una columna a un modelo y le da un valor predeterminado. Pero olvidé actualizar todas las instancias preexistentes de ese modelo para tener ese valor predeterminado para la nueva columna.

En base a esta afirmación, solo intentas probar que un modelo "viejo" tiene el valor predeterminado, ¿correcto?

Teóricamente estás probando si los rieles funcionan. Es decir, "¿Los rieles establecen un valor predeterminado para una columna recién agregada?"

Agregar una columna y establecer un valor predeterminado estará allí en los registros "antiguos" de su base de datos.

Entonces, no necesita actualizar los otros registros para reflejar la configuración predeterminada, entonces. En teoría, no hay nada que probar, ya que los rieles lo han probado por ti. Por último, la razón para usar los valores predeterminados es para no tener que actualizar las instancias previas para usar ese valor predeterminado, ¿verdad?


3
2018-05-23 16:27



Solo creo una instancia de la clase, luego llamo up o down en eso.

Por ejemplo:

require Rails.root.join(
  'db',
  'migrate',
  '20170516191414_create_identities_ad_accounts_from_ad_account_identity'
)

describe CreateIdentitiesAdAccountsFromAdAccountIdentity do
  subject(:migration) { described_class.new }

  it 'properly creates identities_ad_accounts from ad account identities' do
    create_list :ad_account, 3, identity_id: create(:identity).id

    expect { suppress_output { migration.up } }
      .to change { IdentitiesAdAccount.count }.from(0).to(3)
  end
end

3
2018-05-16 21:09



No sé Rails, pero creo que el enfoque es el mismo independientemente de las herramientas Yo uso el siguiente enfoque:

  • asegúrese de que las versiones implementadas de las secuencias de comandos de la base de datos estén etiquetadas / etiquetadas de manera adecuada en el Control de versiones
  • basado en eso necesita al menos tres scripts: un script que crea la versión anterior desde cero (1), un script que crea la nueva versión desde cero (2) y un script que crea la nueva versión desde la versión anterior (3) .
  • crear dos instancias db / schemata En un script de ejecución 2, en el otro script de ejecución 1 seguido de script 3
  • compare los resultados en las dos bases de datos, usando consultas SQL contra el diccionario de datos.

Para probar también el efecto en datos reales, cargue datos de prueba en las bases de datos después de ejecutar el script 2 y entre 1 y 3. De nuevo ejecute consultas SQL, compare los resultados


0
2018-05-25 17:08



Podría considerar ejecutar partes aisladas de su suite de pruebas con configuraciones específicas y copias de sus datos de producción (por ejemplo, algo así como yaml_db)

Es un poco meta, y si sabes cuáles son los posibles problemas con tus nuevas migraciones, es mejor que los mejores para cubrir tus necesidades específicas, pero es posible.


0
2018-06-18 19:55