Rails & RSpec:使用预先存在的记录测试数据库

Rails & RSpec: test DB with preexisting records

我以前的所有项目都使用 DatabaseCleaner,所以我习惯于从一个空的数据库开始,并在每个测试中使用 FactoryGirl 创建测试数据。

目前,我正在从事一个项目,该项目有一个包含许多记录的测试数据库。这是一个 sql 文件,所有开发人员都必须在其本地测试环境中导入该文件。在持续集成服务器中导入相同的数据库。我觉得对测试数据的控制越少,测试过程就越难。

某些功能允许他们的测试专注于特定数据,例如与特定用户关联的记录。在那些情况下,先前存在的数据是无关紧要的。显示所有客户项目的报告等其他功能不允许我 "ignore" 预先存在的数据。

有没有办法在某些测试中忽略测试数据库的内容(模拟一个空数据库并创建我自己的测试数据而不实际删除测试数据库中的所有行)?也许有两个数据库(都在同一个 MySQL 服务器中)并且能够在它们之间切换(例如,一些测试使用一个数据库,其他测试使用另一个数据库)?

还有其他关于如何处理这种情况的建议吗?

谢谢。

我建议保留您的 test_database 和 'test' 环境作为您的 'clean' 状态。然后您可以设置一个单独的数据库,您最初将其作为 'dirty' 数据库。 rails_helper 文件中的 before 挂钩也可以这样设置:

RSpec.configure do |config|
  config.before :each, type: :feature do |example|
    if ENV['TEST_DIRTY'] || example.metadata[:test_dirty]
      ActiveRecord::Base.establish_connection(
        {
          :adapter => 'mysql2',
          :database => 'test_dirty',
          :host => '127.0.0.1',
          :username => 'root',
          :password => 'password'
        }
      )
    end
  end
end

您的 database.yml 文件需要为您的 'dirty' 数据库添加配置。但我认为这里的关键是将干净和肮脏的状态分开。干杯!

我发现将以下配置添加到 spec/rails_helper.rb 将 运行 测试中的所有数据库操作或 before(:each) 块作为事务,在每次测试完成后回滚。这意味着我们可以做类似 before(:each) { MyModel.delete_all } 的事情,创建我们自己的测试数据,运行 我们的断言(它只会看到我们创建的数据)并且在测试结束后,所有预先存在的数据仍将是在数据库中,因为删除将被回滚。

RSpec.configure do |config|
  config.use_transactional_fixtures = true
end