ruby-on-rails - 在 Rails 中加载夹具数据库

标签 ruby-on-rails postgresql rspec-rails database-cleaner

我正在构建一个 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

我对这两种策略都使用截断的原因是我更喜欢在示例之间完全刷新id值(这样如果我创建,然后在第二个测试中使用 create,第二个示例的 ID 应为 1 而不是 2)。我不确定各种策略的确切含义 - 我找到了 this question这似乎是用 SQL 语法来解释它们,但我对 that 不是很熟悉,所以我的理解仍然很模糊。我相信数据库是 使用 PostgreSQL 管理,但我很少需要通过它直接与它交互,所以我不是特别有经验。

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

编辑:根据评论中的讨论,我怀疑我可能想要删除 Database Cleaner 并改用默认的 Rails fixtures。我已经尝试过了,唯一遇到的问题与我在上述 transaction 策略中遇到的问题相同。即:回滚测试创建的记录时,id 不会回滚,这是一种尴尬的行为。如果我为了运行测试而创建一个 user,将它称为 User.find(1) 会很方便,如果 id 不会重置。

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

最佳答案

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

概念上的差异确实很大。

Fixture 就像这个巨大的静态虚拟数据集,每个示例都被扔进数据库,然后通过事务重置。 fixtures 的一大缺点是你拥有的 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

关于ruby-on-rails - 在 Rails 中加载夹具数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52150918/

相关文章:

postgresql - cron 作业从 debian 上的 postgres 中删除旧数据

ruby-on-rails - RSpec 测试自定义验证器

ruby-on-rails - 测试 Controller 方法。规范

ruby-on-rails - before_filter set_locale 除了 Controller

sql - 如何从pgsql中的列表中选择数据

ruby-on-rails - Rails rake 数据库 :migrate aborts with generated model

postgresql - 无法使用对等 VPC 网络的专用 IP 访问 Google Cloud SQL

ruby-on-rails - Rspec - 测试方法的实例

ruby-on-rails - Rails 3 查询字符串

ruby-on-rails - Rails 使用 select2(和 simple_form)充当可标记的