mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Sync test DB from schema using its SHA1
Previously, we used the migration status to determine whether the test database(s) needed to be reloaded from the schema. This worked in most cases, but if a schema.rb was modified outside of migrations or if a migration was rolled back, it would require a manual db:test:prepare. This commit updates load_schema to record the SHA1 of the loaded schema file inside of the ar_internal_metadata table. We can then use this SHA to determine whether we should reload the schema. This ensures that the test DB stays exactly in sync with the schema file, including rollbacks which fixes a test marked TODO.
This commit is contained in:
parent
eb4faa13e8
commit
ba093a5ada
3 changed files with 25 additions and 13 deletions
|
@ -587,18 +587,22 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def load_schema_if_pending!
|
||||
if Base.connection.migration_context.needs_migration? || !Base.connection.migration_context.any_migrations?
|
||||
current_config = Base.connection_config
|
||||
all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
|
||||
|
||||
unless all_configs.all? { |config| Tasks::DatabaseTasks.schema_up_to_date?(config.config) }
|
||||
# Roundtrip to Rake to allow plugins to hook into database initialization.
|
||||
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
|
||||
FileUtils.cd(root) do
|
||||
current_config = Base.connection_config
|
||||
Base.clear_all_connections!
|
||||
system("bin/rails db:test:prepare")
|
||||
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
|
||||
Base.establish_connection(current_config)
|
||||
end
|
||||
check_pending!
|
||||
end
|
||||
|
||||
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
|
||||
Base.establish_connection(current_config)
|
||||
|
||||
check_pending!
|
||||
end
|
||||
|
||||
def maintain_test_schema! #:nodoc:
|
||||
|
|
|
@ -332,10 +332,21 @@ module ActiveRecord
|
|||
end
|
||||
ActiveRecord::InternalMetadata.create_table
|
||||
ActiveRecord::InternalMetadata[:environment] = environment
|
||||
ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
|
||||
ensure
|
||||
Migration.verbose = verbose_was
|
||||
end
|
||||
|
||||
def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary")
|
||||
file ||= dump_filename(spec_name, format)
|
||||
|
||||
return true unless File.exist?(file)
|
||||
|
||||
ActiveRecord::Base.establish_connection(configuration)
|
||||
return false unless ActiveRecord::InternalMetadata.table_exists?
|
||||
ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
|
||||
end
|
||||
|
||||
def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc:
|
||||
require "active_record/schema_dumper"
|
||||
filename = dump_filename(spec_name, format)
|
||||
|
@ -467,6 +478,10 @@ module ActiveRecord
|
|||
def local_database?(configuration)
|
||||
configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
|
||||
end
|
||||
|
||||
def schema_sha1(file)
|
||||
Digest::SHA1.hexdigest(File.read(file))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -232,10 +232,7 @@ module ApplicationTests
|
|||
assert_successful_test_run("models/user_test.rb")
|
||||
end
|
||||
|
||||
# TODO: would be nice if we could detect the schema change automatically.
|
||||
# For now, the user has to synchronize the schema manually.
|
||||
# This test case serves as a reminder for this use case.
|
||||
test "manually synchronize test schema after rollback" do
|
||||
test "automatically synchronizes test schema after rollback" do
|
||||
output = rails("generate", "model", "user", "name:string")
|
||||
version = output.match(/(\d+)_create_users\.rb/)[1]
|
||||
|
||||
|
@ -268,10 +265,6 @@ module ApplicationTests
|
|||
end
|
||||
RUBY
|
||||
|
||||
assert_successful_test_run "models/user_test.rb"
|
||||
|
||||
rails "db:test:prepare"
|
||||
|
||||
assert_unsuccessful_run "models/user_test.rb", <<-ASSERTION
|
||||
Expected: ["id", "name"]
|
||||
Actual: ["id", "name", "age"]
|
||||
|
|
Loading…
Reference in a new issue