90

经过重大故障排除后,我发现我需要运行rake spec一次(我可以使用 control-c 中止),然后才能直接运行 rspec(例如,在我们规范的子集上)。我们正在运行 Rails 3.0.7 和 RSpec 2.5.0。

显然,rake 正在运行一些重要的数据库设置任务/代码(我们在根级 rails Rakefile 和可能的其他地方有自定义代码)。

如何在不运行的情况下运行 rake 测试数据库设置任务/代码rake spec

除了能够在文件子集上运行 rspec 之外,我还使用specjour将我们的规范传播到多个核心(尚未成功将它们传播到 LAN 中),但我看到与运行 rspec 相同的行为直接:rake spec在specjour工作之前,我需要在每个测试数据库上运行(假设有两个核心):

rake spec TEST_ENV_NUMBER=1
control-c (after tests start)
rake spec TEST_ENV_NUMBER=2
control-c (after tests start)
specjour

注意:我的 config/database.yml 有这个测试条目(对于并行测试 gem 来说很常见):

test:
  adapter: postgresql
  encoding: unicode
  database: test<%=ENV['TEST_ENV_NUMBER']%>
  username: user
  password:

parallel_tests似乎正确地设置了它的数据库,但是我们的许多规范都失败了。

我还应该提到,运行specjour prepare会导致 Postgres 记录它找不到数据库的错误,但它会创建它们(没有表)。在随后的运行中,不会记录任何错误,也不会创建表。有可能我的整个问题只是一个错误prepare,所以我在 github 上报告了它。

我认为我可以通过Specjour::Configuration.prepare在 .specjour/hooks.rb 中设置来在每个 specjour 测试数据库上运行任意代码,所以如果有任何 rake 任务或我需要运行的其他代码,它可能在那里工作。

4

6 回答 6

186

我建议删除您的测试数据库,然后重新创建并迁移:

bundle exec rake db:drop RAILS_ENV=test
bundle exec rake db:create RAILS_ENV=test
bundle exec rake db:schema:load RAILS_ENV=test

在这些步骤之后,您可以运行您的规范:

bundle exec rspec spec

gerry3指出:

一个更简单的解决方案是运行rake db:test:prepare

但是,如果您使用的是 PostgreSQL,这将不起作用,因为 rails 环境已加载,这会打开数据库连接。这会导致prepare调用失败,因为无法删除 DB。棘手的事情。

于 2012-06-22T14:53:22.167 回答
15

提供的解决方案都需要加载 Rails 环境,在大多数情况下,由于开销非常大且速度非常低,这不是所需的行为。DatabaseCleanergem 也相当慢,它为您的应用程序添加了另一个依赖项。

由于上述原因,经过数月的懊恼和烦恼,我终于找到了以下解决方案正是我所需要的。它很好,简单而且快速。在spec_helper.rb

config.after :all do
  ActiveRecord::Base.subclasses.each(&:delete_all)
end

最好的部分是:它只会清除您有效接触过的那些表(未接触的模型不会被加载,因此不会出现在 中,这也是在测试之前subclasses这不起作用的原因)。此外,它在测试后执行,因此(希望)绿点会立即出现。

唯一的缺点是,如果您在运行测试之前有一个脏数据库,它将不会被清理。但我怀疑这是一个主要问题,因为外部测试通常不会触及测试数据库。

编辑

看到这个答案已经获得了一些人气,我想对其进行编辑以保持完整性:如果您想清除所有表格,即使是未触及的表格,您应该能够执行以下“hacks”之类的操作。

subclassesHack 1 - 为方法预加载所有模型

在调用之前对此进行评估subclasses

Dir[Rails.root.join("app", "models", "**", "*.rb")].each(&method(:require))

请注意,此方法可能需要一些时间!

技巧 2 - 手动截断表格

ActiveRecord::Base.connection.tables.keep_if{ |x| x != 'schema_migrations' }

将为您提供所有表名,您可以执行以下操作:

case ActiveRecord::Base.configurations[Rails.env]["adapter"]
when /^mysql/, /^postgresql/
  ActiveRecord::Base.connection.execute("TRUNCATE #{table_name}")
when /^sqlite/
  ActiveRecord::Base.connection.execute("DELETE FROM #{table_name}")
  ActiveRecord::Base.connection.execute("DELETE FROM sqlite_sequence where name='#{table_name}'")
end
于 2013-08-04T03:37:08.297 回答
15

我在工作中设置 CI 系统时遇到了类似的问题,所以我逐渐建立了一个系统来处理这个问题。这可能不是最好的解决方案,但它适用于我的情况,而且我一直在寻找更好的方法来做事。

我有一个需要设置的测试数据库,但还需要加载种子数据才能使我们的测试正常工作。

rake 任务故障排除的基础是使用 --trace 选项运行 rake 以查看幕后发生的情况。当我这样做时,我发现运行 rake spec 做了很多我可以在自定义 rake 任务中复制(或修改)的事情。

这是我们所做的一个例子。

desc "Setup test database - drops, loads schema, migrates and seeds the test db"
task :test_db_setup => [:pre_reqs] do
  Rails.env = ENV['RAILS_ENV'] = 'test'
  Rake::Task['db:drop'].invoke
  Rake::Task['db:create'].invoke
  result = capture_stdout { Rake::Task['db:schema:load'].invoke }
  File.open(File.join(ENV['CC_BUILD_ARTIFACTS'] || 'log', 'schema-load.log'), 'w') { |f| f.write(result) }
  Rake::Task['db:seed:load'].invoke
  ActiveRecord::Base.establish_connection
  Rake::Task['db:migrate'].invoke
end

这只是一个示例,并且针对我们的情况,因此您需要弄清楚需要做什么来设置您的测试数据库,但是使用 rake 的 --trace 选项很容易确定。

此外,如果您发现测试设置花费的时间太长(就像在我们的案例中那样),您还可以将数据库转储为 .sql 格式,并将测试数据库通过管道直接导入 mysql 以进行加载。通过这种方式,我们可以节省几分钟的测试数据库设置。我没有在这里展示它,因为它使事情变得非常复杂——它需要正确生成而不会过时等。

高温高压

于 2011-05-07T16:48:33.017 回答
7

看来,在 Rails 4.1+ 中,最好的解决方案是简单地将ActiveRecord::Migration.maintain_test_schema!rails_helper添加到require 'rspec/rails'.

即您不必再担心必须准备数据库了。

https://relishapp.com/rspec/rspec-rails/docs/upgrade#pending-migration-checks

于 2015-05-20T10:00:57.990 回答
3

在 spring-ified Rails 4 应用程序中,我bin/setup通常被扩充为包含

puts "\n== Preparing test database =="
system "RAILS_ENV=test bin/rake db:setup"

这与利维坦的答案非常相似,加上播种测试数据库,如

rake db:setup # 创建数据库,加载模式,并使用种子数据进行初始化
(用于
db:reset 也先删除数据库)

正如评论所提到的,如果我们想先删除数据库,rake db:reset就这样做。

我还发现,与rake db:test:prepare.

于 2015-07-07T19:56:38.493 回答
0

我首先删除了我的测试数据库 rake db:drop RAILS_ENV=test

当尝试创建一个新的测试数据库时,我遇到了一个问题,因为我的用户帐户与拥有数据库的帐户不同,所以我在 PostgreSQL 中创建了数据库。

键入psql命令提示符,然后运行以下命令以创建一个使用您自己以外的帐户的测试数据库。 CREATE DATABASE your_database_name OWNER your_db_owner;

然后在测试环境中运行您的迁移。 rake db:migrate RAILS_ENV=test

于 2020-06-15T15:47:14.380 回答