Как мне проверить Rails-миграции? - PullRequest
56 голосов
/ 21 мая 2011

Я хочу проверить, выполняются ли определенные условия после выполнения миграции, которую я написал.Каков на данный момент лучший способ сделать это?

Чтобы сделать это конкретнее: я сделал миграцию, которая добавляет столбец в модель и присваивает ему значение по умолчанию.Но я забыл обновить все существующие ранее экземпляры этой модели, чтобы иметь значение по умолчанию для нового столбца.Ни один из моих существующих тестов не поймет этого, потому что все они начинаются со свежей базы данных и добавляют новые данные, которые будут иметь значения по умолчанию.Но если я начну работать, я знаю, что все пойдет не так, и я хочу, чтобы мои тесты сказали мне это.

Я нашел http://spin.atomicobject.com/2007/02/27/migration-testing-in-rails/,, но не пробовал.Это очень старое.Это современное состояние?

Ответы [ 5 ]

19 голосов
/ 14 апреля 2012

Питер Марклунд имеет примерный пример тестирования миграции здесь: https://gist.github.com/700194 (в rspec).

Обратите внимание, что после его примера миграции изменились на использование методов экземпляра вместо методов класса.

Вот резюме:

  1. Создать миграцию как обычно
  2. Создайте файл для тестирования миграции. Предложения: test/unit/import_legacy_devices_migration_test.rb или spec/migrations/import_legacy_devices_migration_spec.rb ПРИМЕЧАНИЕ: вам, вероятно, нужно явно загрузить файл миграции, так как rails, вероятно, не загрузит его для вас. Примерно так должно поступить: require File.join(Rails.root, 'db', 'migrate', '20101110154036_import_legacy_devices')
  3. Миграции (как и все в рубине) просто класс. Проверьте методы up и down. Если ваша логика сложна, я рекомендую рефакторизовать биты логики в меньшие методы, которые будет легче протестировать.
  4. Перед вызовом up настройте некоторые данные так, как это было бы до вашей миграции, и подтвердите, что это состояние - то, что вы ожидаете после.

Надеюсь, это поможет.

ОБНОВЛЕНИЕ : С момента публикации я разместил в своем блоге пример теста миграции .

ОБНОВЛЕНИЕ : Вот идея тестирования миграций даже после того, как они были запущены в процессе разработки.

РЕДАКТИРОВАТЬ : я обновил мое доказательство концепции до полного файла спецификации, используя надуманный пример из моего блога.

# 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
4 голосов
/ 17 мая 2017

Я просто создаю экземпляр класса, затем вызываю up или down для него.

Например:

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 голосов
/ 23 мая 2011

Я выполнил миграцию, которая добавляет столбец в модель и присваивает ему значение по умолчанию.Но я забыл обновить все существующие ранее экземпляры этой модели, чтобы иметь значение по умолчанию для нового столбца.

Основываясь на этом утверждении, вы просто пытаетесь проверить эту «старую» модель, имеет значение по умолчанию, правильно?

Теоретически вы тестируете, работает ли рельсы.То есть, "устанавливает ли rails значение по умолчанию для вновь добавленного столбца"

Добавление столбца и установка значения по умолчанию будет в "старых" записях вашей базы данных.

Итак,тогда вам не нужно обновлять другие записи, чтобы они отражали настройку по умолчанию.Теоретически проверять нечего, так как рельсы проверили это для вас.Наконец, причина использования значений по умолчанию состоит в том, что вам не нужно обновлять предыдущие экземпляры для использования этого значения по умолчанию, верно?

0 голосов
/ 18 июня 2015

Вы могли бы рассмотреть возможность запуска изолированных частей вашего набора тестов с конкретными настройками для копий ваших производственных данных (например, что-то вроде yaml_db ).

Это немного мета, и если выЗнайте, какие потенциальные проблемы возникают с вашими новыми миграциями, и вам, вероятно, будет лучше, если вы просто улучшите их, чтобы удовлетворить ваши конкретные потребности, но это возможно.

0 голосов
/ 25 мая 2011

Я не знаю Rails, но я думаю, что подход одинаков независимо от инструментов Я использую следующий подход:

  • убедитесь, что развернутые версии сценариев базы данных апропиатически помечены / помечены в Version Control
  • исходя из того, что вам нужно как минимум три скрипта: скрипт, который создает старую версию с нуля (1), скрипт, который создает новую версию с нуля (2) и скрипт, который создает новую версию из старой версии (3).
  • создать два экземпляра / схемы БД. В одном сценарии запуска 2, в другом сценарии запуска 1 следует сценарий 3
  • сравните результаты в двух базах данных, используя sql запросы к словарю данных.

Чтобы проверить также влияние на фактические данные, загрузите тестовые данные в базы данных после выполнения сценария 2 и между 1 и 3. Снова выполните SQL-запросы, сравните результаты

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...