【问题标题】:Why would rails not reset the test database between runs为什么rails不会在运行之间重置测试数据库
【发布时间】:2014-08-03 10:42:34
【问题描述】:

rails 代码库中有 cmets 指示应该在运行之间重置测试数据库

耙-T

rake test:all                           # Run tests quickly by merging all types and not resetting db
rake test:all:db                        # Run tests quickly, but also reset db

config/database.yml

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:

对我来说似乎不是这样。

我正在使用工厂女孩生成测试模型,这里是一个示例工厂

FactoryGirl.define do
  factory :podcast do
    sequence(:title)     { |n| "Podcast #{n}" }
    sequence(:feed_url)  { |n| "http://podcast.com/#{n}" }
  end
end

播客应该有一个唯一的 feed_url,所以我验证它在模型中的唯一性。

class Podcast < ActiveRecord::Base
  validates :feed_url, uniqueness: true, presence: true
end

test_helper.rb我lint所有工厂

ENV["RAILS_ENV"] ||= "test"
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/autorun'

FactoryGirl.lint

我的测试创建了一个播客,构建了另一个同名的播客,然后断言第二个 无效。

require 'test_helper'

describe Podcast do
  describe '#feed_url' do
    it 'must be unique' do
      podcast = create(:podcast)
      new_podcast = build(:podcast, feed_url: podcast.name)

      assert_invalid podcast, :feed_url, 'has already been taken'
    end
  end
end

我第一次运行测试时,它执行时没有错误并且测试全部通过。 我第二次运行测试时,Factory Girl lint 失败,因为播客 feed_url 已经被占用。

为什么没有在两次运行之间重建测试数据库?

【问题讨论】:

    标签: ruby-on-rails testing factory-bot minitest


    【解决方案1】:

    我们有一个更复杂的 FactoryGirl 设置,它为我们的数据库准备了一些规范项目,但我认为您可以直接将此代码放入您的 test_helper.rb 以确保数据库被清空:

    # Destroy all models because they do not get destroyed automatically
    (ActiveRecord::Base.connection.tables - %w{schema_migrations}).each do |table_name|
      ActiveRecord::Base.connection.execute "TRUNCATE TABLE #{table_name};"
    end
    

    或者,在每次运行之前运行rake db:test:prepare

    您也可以使用一个 gem,但我没有任何经验:http://rubygems.org/gems/database_cleaner

    【讨论】:

      【解决方案2】:

      数据库未重置的原因是您在 rails 提供的数据库事务之外运行测试。 ActiveSupport::TestCase 类是所有 Rails 测试的基础。 ActiveRecord 为这个类添加了一个按测试的数据库事务。此事务将在每次测试后重置数据库。但是您没有使用 ActiveSupport::TestCase 运行测试,而是使用未配置为运行事务的 Minitest::Spec 运行测试。

      最简单的解决方案是将 minitest-rails 添加到 Gemfile 中,并将 test_helper.rb 文件中的 require 从 minitest/autorun 更改为 minitest/rails。如果您希望自己添加对 Minitest 规范 DSL 的支持,可以使用 this article 作为起点。

      【讨论】:

      • 感谢您回答问题,与 rdnewman 建议的在运行之间截断数据库相比,在测试之间使用事务回滚是否有优势?
      【解决方案3】:

      您是否有其他工厂可能正在通过关联创建播客?

      FactoryGirl linting 构建每个工厂并检查其有效性,如果另一个工厂有一个播客作为关联,它将创建一个播客记录。

      FactoryGirl 建议在运行 linting 后清除数据库。他们在示例中使用database_cleanerhttps://github.com/thoughtbot/factory_girl/blob/2bf15e45305ac03315cf2ac153db523d3ce89ce1/GETTING_STARTED.md#linting-factories

      【讨论】:

      • 我接受了 rdnewman 的回答,因为它没有引入更多的依赖项。你能说明使用 database_cleaner 的理由吗?
      • 如果 rdnewman 的答案对你有用,那么我会坚持下去,这很简单。 database_cleaner 实现了相同的目标,只是恰好支持更多的 ORM 和更多的数据库清理策略。
      猜你喜欢
      • 1970-01-01
      • 2021-11-19
      • 2015-08-08
      • 1970-01-01
      • 1970-01-01
      • 2018-01-09
      • 2012-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多