在Rails中加载夹具数据库

问题描述 投票:1回答:1

我正在构建一个Rails应用程序(我是新手,所以请原谅我,如果一些措辞是笨拙的)。我正在尝试编写测试(使用RSpec)绘制和使用数据库中的数据,我在编写测试时遇到了麻烦。

某些测试(例如注册用户或创建内容)似乎最适合拥有一个新的数据库,而有些则需要数据库填充的数据库。

目前我正在使用数据库清理器gem,具有以下配置:

  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
    DatabaseCleaner.strategy = :truncation   end

  # start the transaction strategy as examples are run    
   config.around(:each) do |example|
     DatabaseCleaner.cleaning do
       example.run
     end    
   end

我在两种策略中使用truncation的原因是我更喜欢在示例之间完全刷新id值(因此,如果我在一次测试中使用create,然后在第二次测试中使用create,则第二个示例应该具有id 1而不是2 )。我不确定各种策略究竟是什么意思 - 我发现this question似乎用SQL语法来解释它们,但我对此并不十分熟悉,所以我的理解仍然很模糊。我相信数据库是用PostgreSQL管理的,但我很少通过它直接与它进行交互,所以我不是特别有经验。

因此,我的数据库完全被删除并在每个示例之间从头开始构建 - 如果我想要一个干净的数据库,那么这是理想的,但如果我想简单地加载灯具,那么创建所有模型可能需要一段时间。感觉我应该能够拥有一个“缓存”版本的灯具,我可以加载它适合的那些例子。但我不知道怎么做,如果有可能的话。有办法吗?

编辑:在评论中讨论之后,我怀疑我可能想要删除数据库清理程序并使用默认的Rails工具。我试过这个,我遇到的唯一问题就像我上面描述的transaction策略一样。也就是说:当回滚测试创建的记录时,id不会回滚,这是一种尴尬的行为。如果我为了运行测试而创建一个user,那么就像User.find(1)一样引用它是很方便的,如果id没有重置则这是不可能的。

这可能是某种红旗,我不应该这样做(我愿意做其他事情)。我也意识到我可以说User.first得到相同的行为,这可能会更好。我不确定什么是合适的。

ruby-on-rails postgresql rspec-rails database-cleaner
1个回答
1
投票

DatabaseCleaner不适用于灯具。它旨在与工厂一起使用。 ActiveRecord::Fixtures有自己的回滚机制。

有一个非常大的概念差异。

Fixtures就像这组巨大的静态虚拟数据,每个示例都被抛入数据库,然后通过事务重置。固定装置的最大特点是,您拥有的固定装置越多,应用程序的初始状态就越复杂,并且它会促使测试和固定装置之间的紧密耦合。

这是一个示例,显示了“Marko Anastasov”值如何从代码之外的某处神奇地出现:

RSpec.describe User do
  fixtures :all

  describe "#full_name" do
    it "is composed of first and last name" do
      user = users(:marko)
      expect(user.full_name).to eql "Marko Anastasov"
    end
  end
end

尽管最近由于感觉简单(以及Minitest),灯具已经复苏。

工厂是生产独特记录的对象工厂。您可以使用空白状态启动每个示例,然后使用工厂以准确的状态填充数据库以复制您正在测试的方案,而不是让一堆垃圾浮动。如果做得好,这可以最大限度地减少测试订购问题,拍打测试和更换灯具破坏测试。

RSpec.describe User do
  describe "#full_name" do
    it "is composed of first and last name" do
      user = FactoryBot.create(:user)
      expect(user.full_name).to eql "#{user.first_name} #{user.last_name}"
    end
  end
end

这是一个生成伪随机值的好工厂的示例:

require 'ffaker'

FactoryBot.define do
  factory :user do
    first_name { FFaker::Name.first_name }
    last_name { FFaker::Name.last_name }
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.