我是Rspec和Factory girl的新手,希望我的测试能够在特定的数据库状态下运行。我知道我可以让Factory girl创建这些记录,并且在测试运行后对象将被销毁,但是如果我在数据库中有数据会发生什么。
例如:我希望我的测试在我通过Factory Girl创建的数据库中有3条记录时运行。但是,我目前在数据库中已有1个模型记录,我不想仅为测试删除它。在那里有一个模型毁了我的测试。
数据库内容
[#<Leaderboard id: 1, score: 500, name: "Trudy">]
leaderboard_spec.rb
require 'spec_helper'
describe Rom::Leaderboard do
describe "poll leaderboard" do
it "should say 'Successful Run' when it returns" do
FactoryGirl.create(:leaderboard, score: 400, name: "Alice")
FactoryGirl.create(:leaderboard, score: 300, name: "Bob")
FactoryGirl.create(:leaderboard, score: 200, name: "John")
Leaderboard.highest_scorer.name.should == "Alice"
end
end
end
现在我的测试会失败,因为它会错误地认为Trudy是得分最高的,因为测试运行的状态不正确。
工厂女孩是否提供从数据库中删除记录然后回滚此删除?与它在数据库中创建记录和回滚的方式类似
答案 0 :(得分:37)
使用database_cleaner
宝石很受欢迎。你可以在这里找到它:
https://github.com/bmabey/database_cleaner
文档建议使用以下rspec配置:
RSpec.configure do |config|
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
这将确保每个测试都有一个干净的数据库。
答案 1 :(得分:0)
尽可能直接回答您的回滚问题:没有办法在测试中回滚删除。
遵循测试约定,您的目标通常是从一个干净的平板开始,并使用factory_girl在您需要测试的数据库中有效地构建场景。
您可以通过将其添加到leaderboards.rb工厂文件中来完成您想要的任务:
factory :trudy do
id 1
score 500
name "Trudy"
end
或者您可以在测试文件中创建一个简单的辅助函数,在需要测试时重新生成该记录:
def create_trudy
FactoryGirl.create :leaderboard,
id: 1,
score: 500,
name: "Trudy"
end
end
或者您可以将所有这些放在描述块中的before(:suite)中,如下所示:
describe "with a leaderboard record existing" do
before(:each) do
FactoryGirl.create :leaderboard, id: 1, score: 500, name: "Trudy"
end
# Tests with an initial leaderboard record
end
describe "with no leaderboard records initially" do
# Your test above would go here
end
在最后的建议中,您的测试变得非常具有描述性,在查看输出时,您将确切知道数据库在每次测试开始时的状态。