【问题标题】:Factory Girl Traits工厂女孩特征
【发布时间】:2013-07-06 00:28:30
【问题描述】:

在尝试编写 rSpec 测试时,我对如何生成具有关联的 FactoryGirl 记录有点困惑。

基本上,我有一个Quiz 模型和一个Question 模型。它们通过 HABTM 关联关联。

这是我的Quiz工厂:

FactoryGirl.define do
  factory :quiz do
    description 'Test'

    # after(:create) { |quiz| quiz.create_sample_questions }

    # trait :with_questions do
    #   after :create do |quiz|
    #     5.times do |q|
    #       quiz.questions << FactoryGirl.create(:question, :with_answers)
    #     end
    #   end
    # end
  end
end

最好在这里创建一个特征,然后为测验创建示例问题吗?还是我应该使用 after create 方法来做到这一点?

似乎都不起作用,而且我的特质似乎不会引起问题。

谢谢!

【问题讨论】:

  • 迟到了,但是,您能否发布您的question 工厂以及您如何调用具有with_questions 特征的quiz

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


【解决方案1】:

我更喜欢使用特征,因为它们可以让规范不那么混乱。当然,重要的是要确保工厂本身不会变得太杂乱。

每当我定义一个构建关联的特征时,我都会确保我可以在关联中构建可变数量的记录,FactoryGirls 可以很容易地做到这一点:

FactoryGirl.define do
  factory :quiz do
    description 'Test'

    trait :with_questions do
      ignore    { question_count 5 }
      questions { build_list(:question, question_count) }
    end
  end
end

您现在可以在您的规范中构建或创建测验:

FactoryGirl.create(:quiz, :with_questions)
FactoryGirl.build(:quiz, :with_questions, question_count: 2)

请注意,该 trait 使用 build_list,因此默认情况下它不会保留问题,并使用 question_count 而不是 questions_count,因此它永远不会与计数器缓存冲突。

为了确保您的规范不会超出他们可能需要做的事情,我不会用答案构建问题,而只是提出问题(除非您的验证需要它们)。如果在某些时候你确实需要有答案的问题,你可以添加另一个 trait:

FactoryGirl.define do
  factory :quiz do
    description 'Test'

    ignore { question_count 5 }
    trait :with_questions do
      questions { build_list(:question, question_count) }
    end

    trait :with_answered_questions do
      questions { build_list(:question, question_count, :with_answers) }
    end
  end
end

有关使用与 FactoryGirl 的关联的更多信息,请参阅FactoryGirl documentation

【讨论】:

【解决方案2】:

我有兴趣看到这个问题的其他答案,但我可以将我的个人经验与使用工厂、关联和使用回调自动加载一堆对象联系起来。

基本上,我发现我尝试使用特征和回调获得的“更高级”,我对我的规范的未来造成的麻烦越多。有了这种扭曲的逻辑,你最终会遇到一堆乱七八糟的工厂,你会摸不着头脑想知道到底发生了什么。

完全假设的问题: 如果稍后您需要一个包含 4 个问题的测验怎么办?好吧,每个 quiz :with_questions 都包含 5 个问题。然后你会创建一个名为with_4_questions 的特征吗? ;)

根据我的这种经验,我建议您首先在您的规范中生成单独的模型并保持简单。不要抽象出太多回调背后的逻辑。

假设我正在使用您的模型编写功能规范。这就是我将如何做你想要完成的事情:

feature 'User edits a question' do
  let!(:quiz) { FactoryGirl.create(:quiz) }

  before do
    5.times { FactoryGirl.create(:question, quiz: quiz) }
  end

  scenario 'with valid input' do
    # ...
  end
end

如果您发现自己经常需要一个 quiz 和 5 个 questions,您可以使用 Railscasts 演示的方法创建一个 macro。至少你可以创建一个可以传递参数的方法,比如上面我的完全假设的问题中的num_questions

【讨论】:

  • 谢谢,真的很有帮助!
  • 我发布了一种不同的方法,它也以不同的方式回答了您完全假设的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多