为什么要运行“rake db:migrate RAILS_ENV=test”命令?

71
在Rails 4.0.0.rc1和Ruby 2.0.0中,运行迁移后,通过rspec运行测试时会出现以下错误:
``` /Users/peeja/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/activerecord-4.0.0.rc1/lib/active_record/migration.rb:376:in `check_pending!': Migrations are pending; run 'rake db:migrate RAILS_ENV=test' to resolve this issue. (ActiveRecord::PendingMigrationError) ```
这似乎不正常。没有人会迁移他们的测试数据库,对吧?他们是使用 `db:test:prepare` ,但是我已经忘记做了。因此,我运行了 `rake db:test:prepare` 并再次运行 `rspec` 命令... 结果还是同样的错误。
如果实际上运行 `rake db:migrate RAILS_ENV=test`,则错误确实消失了。
发生了什么事?这在Rails 4中是新功能吗?

1
rake db:test:prepare 是否有效? - itsnikolay
2
对我来说,即使 schema.rb 是最新的,rake db:test:prepare 也不起作用。只有迁移测试数据库才能生效。 - Kris
请查看我的答案,希望能对您有所帮助:https://dev59.com/I2Ei5IYBdhLWcg3wZ7q8#33054787 - Haider Raza
1
rake db:migrate RAILS_ENV=test 对我来说解决了问题。 - nope2023
我通过在 rails_helper.rb 文件中的 RSpec.configure 块之前添加 ActiveRecord::Migration.maintain_test_schema! 来修复了这个问题。文档链接:https://relishapp.com/rspec/rspec-rails/docs/upgrade#pending-migration-checks - Suraj
顺便说一句,但是...迁移测试数据库有什么问题吗?.. - x-yuri
7个回答

78

从Rails 4.1开始,rake db:test:*任务已经被弃用。相反,您的(test|spec)_helper.rb应该包含:

ActiveRecord::Migration.maintain_test_schema!
这意味着每次运行测试时,无论您是从Rake任务运行还是其他方式,您的测试数据库都会获得正确的模式。

这意味着每次运行测试时,无论您是从Rake任务运行还是其他方式,您的测试数据库都会获得正确的模式。


谢谢你提醒我,我想当4.1发布时我错过了这个。 - jipiboily
2
这是正确的,也是我保持测试数据库最新的最佳方法。错误在于“您有待处理的迁移”。但是,如果有人不想遵循这个好的解决方法,我建议您删除测试数据库并重新运行rake db:create RAILS_ENV=test来重新创建测试数据库,然后运行rake db:migrate RAILS_ENV=test来迁移测试数据库。当我还没有为我的应用程序编写测试时,我经常这样做。 - Afolabi Olaoluwa
1
我可以在Rails 5的“tests_helper.rb”文件中直接看到这行代码。 - Abhilash
请小心处理。如果您有多个测试数据库连接,并且没有为它们编写迁移文件,那么 ActiveRecord::Migration.maintain_test_schema! 将不会将开发模式加载到这些连接的测试模式中,您仍然需要手动加载它。 - jlesse
顺便说一句,我无法在Test::Unit中使其工作(例如在test/test_helper.rb中)。 - Dorian

31

看起来 rake test:prepare 生效了,不确定现在 db:test:prepare 具体操作。


哇,一针见血。谢谢!https://gist.github.com/Peeja/5831155 现在要提交一个Rails的bug了... - Peeja
1
哎呀。我第一次发布时错过了 test:prepare 实际上正在调用(依赖于)db:test:prepare。不过,所有好的东西似乎都发生在 db:test:prepare 之外。以下是 Rails 代码:https://github.com/rails/rails/blob/067e1505d4e054df566e065f4faf11ee4b430a3d/activerecord/lib/active_record/railties/databases.rake#L399 - Peeja
看起来数据库是从db:test:load中的'schema.rb'创建的,而test:preparedb:test:prepare之后调用它。但是它似乎也直接从db:test:prepare中调用了db:test:load - Kris
我在代码中看到了这一点,但我非常确定(成功的)Rake::Task#invoke会出现在rake --trace输出中,但实际上我并没有看到它发生。很好奇。 - Peeja

22

你也可以尝试

rake db:migrate RAILS_ENV=test

它的作用是

db:test:prepare

做什么呢:)


9
实际上并不会。rake db:migrate RAILS_ENV=test将迁移测试数据库,而rake db:test:prepare将把模式加载到测试数据库中,这样可以更快速和减少错误。请注意,以上内容已被翻译为通俗易懂的语言,但意思未经修改。 - Peeja

11

有时我仍然很难根据一个人的答案来解决这个问题,所以我把一些步骤组合在一起以获得更好的结果。以下是我采取的步骤,不确定哪些是不必要的,但最终可以解决问题。

  1. ActiveRecord :: Migration.maintain_test_schema!添加到test_helper.rb文件的顶部。
  2. rake test:prepare
  3. rake db:migrate
  4. rake db:migrate RAILS_ENV=test

然后,当我运行bundle exec rake test时,每次都会得到干净的结果且没有待处理的迁移。(这是我在第一次生成脚手架之后所做的)。如果您确切地知道其中某个步骤绝对不必要,请随意纠正我,但这是我确保它每次都能正常工作的方法。


3
我发现在使用`chruby`管理我的Ruby版本时遇到了这个问题。Rails通过系统命令调用`bin/rails db:test:prepare`。它没有利用chruby的`$PATH`环境变量,因此它以系统Ruby的身份运行,并且通常由于缺少gems而失败。不幸的是,我目前还没有好的解决方案。

2
哇,你是怎么发现的?我也在使用 chrubyActiveRecord::Migration.maintain_test_schema! 对我来说根本不起作用。你是如何调试的?有什么解决方法吗? - Paweł Gościcki

0

鉴于您提供的信息,很难为您的情况提供答案。

在我的案例中,它未能“保持架构”(spec/rails_helper.rbActiveRecord::Migration.maintain_test_schema!)。因为我使用了 postgres 数据库(在 Docker 容器中运行)。在这种情况下有两个解决方案:

  • 切换到单独的数据库(不是 postgres
  • 使用 bin/rails db:migrate RAILS_ENV=test

为了给你更多的细节,maintain_test_schema! 的作用是运行 bin/rails db:test:prepare,如果有待处理的迁移。

  • db:test:prepare == db:test:load
  • 在加载模式之前,db:test:load会执行db:test:purge
  • db:test:purge断开与数据库的连接,删除并重新创建数据库。
  • 在删除数据库之前,它建立一个主连接(以postgres用户身份的连接)

-1
你可以尝试在命令之前设置变量,就像这样。 这个语句解决了我的问题:
RAILS_ENV=test rake db:migrate

9
这并没有回答问题。问题是:为什么我们需要运行此迁移,而不是如何修复错误。 - Zhenya
该环境的修改顺序完全没有影响。 - Alicester4WonderlandPresident

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接