your programing

Rails 마이그레이션을 어떻게 테스트하나요?

lovepro 2020. 12. 31. 23:05
반응형

Rails 마이그레이션을 어떻게 테스트하나요?


내가 작성한 마이그레이션을 실행 한 후 특정 조건이 유지되는지 테스트하고 싶습니다. 이를 수행하는 현재 가장 좋은 방법은 무엇입니까?

이를 구체적으로 설명하기 위해 모델에 열을 추가하고 기본값을 제공하는 마이그레이션을 수행했습니다. 그러나 새 열에 대한 기본값을 갖도록 해당 모델의 기존 인스턴스를 모두 업데이트하는 것을 잊었습니다. 내 기존 테스트는 모두 새 데이터베이스로 시작하고 기본값이있는 새 데이터를 추가하기 때문에이를 포착하지 못합니다. 하지만 프로덕션에 착수하면 모든 것이 깨질 것이라는 것을 알고 테스트를 통해이를 알려주고 싶습니다.

http://spin.atomicobject.com/2007/02/27/migration-testing-in-rails/ 찾았 지만 시도하지는 않았습니다. 아주 오래되었습니다. 그게 최첨단인가요?


Peter Marklundhttps://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. 마이그레이션은 (루비의 모든 것과 마찬가지로) 클래스 일뿐입니다. updown방법을 테스트합니다 . 논리가 복잡하다면 테스트하기 더 쉬운 작은 방법으로 논리 조각을 리팩토링하는 것이 좋습니다.
  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

클래스의 인스턴스를 만든 다음 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

모델에 열을 추가하고 기본값을 제공하는 마이그레이션을 수행했습니다. 그러나 새 열에 대한 기본값을 갖도록 해당 모델의 기존 인스턴스를 모두 업데이트하는 것을 잊었습니다.

Based on this statement, you are just trying to test that an "old" model, has the default, correct?

Theoretically you are testing if rails works. I.e., "Does rails set a default value to a newly added column"

Adding a column and setting a default value will be there in the "old" records of your database.

So, you don't need to update the other records to reflect the default setting, then. In theory there is nothing to test, as rails has tested that for you. Lastly, the reason to use defaults is so that you don't have to update the previous instances to use that default, right?


I don't know Rails, but I think the approach is the same independently from the tooling I use the following approach:

  • make sure deployed versions of database scripts are apropiatly tagged/labeled in Version Control
  • based on that you need at least three scripts: a script that creates the old version from scratch (1), a script that creates the new version from scratch (2) and a script that creates the new version from the old version (3).
  • create two db instances/schemata. In one run script 2, in the other run script 1 followed by script 3
  • compare the results in the two databases, using sql queries against the data dictionary.

For testing also the effect on actual data, load test data into the databases after executing script 2 and between 1 and 3. Again run sql queries, compare the results


You could consider running isolated portions of your test suite with specific settings against copies of your production data (with e.g. something like yaml_db).

It's a bit meta, and if you know what the potential problems are with your new migrations you'd likely be better off just enhancing them to cover your specific needs, but it's possible.

ReferenceURL : https://stackoverflow.com/questions/6079016/how-do-i-test-rails-migrations

반응형