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