如果定义了该参数,则分配参数

时间:2014-07-08 22:53:04

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

我已经抽象出我的模型,可以同时测试多个模型。问题是某些模型具有不同的参数。以下为示例模式。

架构(简化)

# Table name: cars
#
#  id         :integer          not null, primary key
#  hp         :integer 
#  wheels     :integer 

# Table name: trucks
#
#  id         :integer          not null, primary key
#  hp         :integer 
#  wheels     :integer 

# Table name: boats
#
#  id         :integer          not null, primary key
#  motors     :integer
#  hp         :integer 

测试

setup do
   @models = ['cars', 'trucks', 'boats']
end

test 'something awesome' do
   @models.each do |model|
    # This works for cars and trucks, not for boats

    exemplar = FactoryGirl.create(model, id: 1, hp: 600, wheels: 4)

    # A bunch of assertions

  end
end

我可以为所有车型分配idhp,但是当汽车和卡车有wheels时,船只有motors。有没有办法在create调用中基本上说“如果定义了这个方法,那么使用它,如果没有则忽略它”

我希望能够做的是致电exemplar = FactoryGirl.create(model, id: 1, hp: 600, wheels: 4, motors: 2)并让它全面运作,创建3个对象:

  1. car:id = 1,hp = 600,wheels = 4
  2. truck:id = 1,hp = 600,wheels = 4
  3. boat:id = 1,hp = 600,motors = 2

1 个答案:

答案 0 :(得分:1)

如果您使用rspec作为测试框架,请在当前上下文中使用shared examples

这将允许您根据需要构建每个对象,并让它们都经历相同的测试。例如:

groupe_example 'object' do
   it 'has a valid factory' do
     expect(object).to be_valid
   end
end

describe Car do
  let(:object){ create(:car_with_some_options) }
  include_examples 'object'
end

describe Truck do
  let(:object){ create(:truck_with_other_options) }
  include_examples 'object'
end

否则,您应该寻求以下解决方案:

setup do
   @models = {:car => {hp: 600}, :truck => { wheels: 8, hp: 1000} }
end

test 'something awesome' do
   @models.each do |model, params|
    # This works for cars and trucks, not for boats

    exemplar = FactoryGirl.create(model, params)

    # A bunch of assertions

  end
end

可以使用不同的工厂更好地重新格式化。例如,如果您为每个模型创建:default_car,:default_truck等工厂,则可以设置您想要的任何参数,然后通过FactoryGirl.create进行简单调用,而不必担心测试中的参数。 / p>

==================编辑========================

如果您确实想测试参数是否已定义,可以使用attributes。更全面的答案是here

或者,更简单的是,您可以检查是否有编写器操作符:

model.public_send(:wheels=, 4) if model.respond_to? :wheels=