为什么我需要迁移 Rails 中的测试数据库?

Why do I need to migrate the test database in Rails?

创建新的迁移文件后,运行 迁移,然后 运行 我收到的测试:

Failure/Error: ActiveRecord::Migration.maintain_test_schema!

ActiveRecord::PendingMigrationError:

  Migrations are pending. To resolve this issue, run:

          bin/rails db:migrate RAILS_ENV=test

rails_helper.rb 中的以下代码片段不是应该为我将迁移应用到测试数据库吗?

# Checks for pending migration and applies them before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!

更新

这是我要求的config/environments/test.rb

Rails.application.configure do
  # Settings specified here will take precedence over those in config/application.rb.

  # The test environment is used exclusively to run your application's
  # test suite. You never need to work with it otherwise. Remember that
  # your test database is "scratch space" for the test suite and is wiped
  # and recreated between test runs. Don't rely on the data there!
  config.cache_classes = true

  # Do not eager load code on boot. This avoids loading your whole application
  # just for the purpose of running a single test. If you are using a tool that
  # preloads Rails for running tests, you may have to set it to true.
  config.eager_load = false

  # Configure public file server for tests with Cache-Control for performance.
  config.public_file_server.enabled = true
  config.public_file_server.headers = {
    'Cache-Control' => 'public, max-age=3600'
  }

  # Show full error reports and disable caching.
  config.consider_all_requests_local       = true
  config.action_controller.perform_caching = false

  # Raise exceptions instead of rendering exception templates.
  config.action_dispatch.show_exceptions = false

  # Disable request forgery protection in test environment.
  config.action_controller.allow_forgery_protection = false
  config.action_mailer.perform_caching = false

  # Tell Action Mailer not to deliver emails to the real world.
  # The :test delivery method accumulates sent emails in the
  # ActionMailer::Base.deliveries array.
  config.action_mailer.delivery_method = :test

  # Print deprecation notices to the stderr.
  config.active_support.deprecation = :stderr

  # Raises error for missing translations
  # config.action_view.raise_on_missing_translations = true
end

您应该 运行 rails db:migrate RAILS_ENV=test 先更新您的测试数据库。

这样做的目的是,Rails 将尝试加载架构,而不仅仅是在测试架构有待处理的迁移时引发。现在只有在加载架构后有待处理的迁移时才会引发异常。

使用此功能时需要注意一些注意事项:

  • 迁移仍然需要 运行 手动进行;虽然现在这只需要在 'development' 环境中完成。
  • 如果架构尚未初始化,将引发异常。异常将提供说明 rake db:migrate 需要 运行.

可能有两个原因。

  1. 您可能错过了config/environments/test.rb
  2. 中的配置

如果没有,请添加 config.active_record.maintain_test_schema = true,如果您已将其设置为 false,请将其设置为 true

来自docs

config.active_record.maintain_test_schema is a boolean value which controls whether Active Record should try to keep your test database schema up-to-date with db/schema.rb (or db/structure.sql) when you run your tests. The default is true.

  1. 架构加载后您可能有待处理的迁移

来自rspec docs

What this does is that rather than just raising when the test schema has pending migrations, Rails will try to load the schema. An exception will now only be raised if there are pending migrations afterwards the schema has been loaded.

使用 rake db:migrate:status

检查您是否有待处理的迁移

另外,如果你使用的是SQLite 3.7.9,你应该看看这个discussion

在您的 运行 测试中,配置按以下顺序加载(除非您在 rails 应用程序中自定义了 autoload_paths 的顺序):

  1. config/application.rb
  2. config/environments/test.rb
  3. spec/rails_helper.rb

因此,您收到的迁移挂起错误一定是由于 config.active_record.migration_error = true 此配置设置之前在 rails 引擎加载 rails_helper.rb 的某处设置,其中 ActiveRecord::Migration.maintain_test_schema! 指令是定义。

尝试在 config/environments/test.rb 上设置 config.active_record.migration_error = false 以跳过迁移检查,如 rspec upgrade guide.[=15= 中所述]