使用Shoulda匹配器的rSpec测试Rails

时间:2013-08-08 20:22:35

标签: ruby-on-rails testing rspec factory-bot shoulda

我已经开始在我的Rails应用程序中学习测试,并且正在使用rSpec和Shoulda。

我有以下测试有效:

it { should respond_to(:park_name) }

然而,我不明白的是,这是什么运行?这是在模型本身或模型的实例上运行,如果它是模型的实例,那么它是否自动使用我的Factory Girl工厂?

关于这里实际发生的事情的任何简单解释?

更新

好的,我有这个:

  describe 'validations' do

    subject { FactoryGirl.build(:coaster) }

    it { should validate_presence_of(:name) }
    it { should validate_presence_of(:speed) }
    it { should validate_presence_of(:height) }

  end

但测试失败了。有什么想法吗?

Coaster.rb:

class Coaster < ActiveRecord::Base

      extend FriendlyId
      friendly_id :slug, use: :slugged

      belongs_to :park
      belongs_to :manufacturer

      attr_accessible :name,
                      :height,
                      :speed,
                      :length,
                      :inversions,
                      :material,
                      :lat,
                      :lng,
                      :park_id,
                      :notes,
                      :manufacturer_id,
                      :style,
                      :covering,
                      :ride_style,
                      :model,
                      :layout,
                      :dates_ridden,
                      :times_ridden,
                      :order,
                      :on_ride_photo



      scope :by_name_asc, lambda {
        order("name ASC")
      }

      scope :made_from, lambda { |material|
        where("material = ?", material)
      }

      scope :wooden, lambda {
        made_from "wood"
      }

      scope :steel, lambda {
        made_from "steel"
      }



      delegate :name, :location_1, :location_2, :location_3, :location_4,
        to: :park,
        allow_nil: true,
        prefix: true

      delegate :name, :url,
        to: :manufacturer,
        prefix: true



      validates :name,
        :presence => true

      validates :height,
        allow_nil: true,
        numericality: {greater_than: 0}

      validates :speed,
        allow_nil: true,
        numericality: {greater_than: 0}

      validates :length,
        allow_nil: true,
        numericality: {greater_than: 0}

测试结果:

  

1)过山车验证应该要求设定速度        失败/错误:它{should validate_presence_of(:spe​​ed)}          当速度设置为nil时,预期错误包括“不能为空”,没有错误        #./spec/models/coaster_spec.rb:75:in'块(3级)in'

     

2)过山车验证应该要求设置高度        失败/错误:它{should validate_presence_of(:height)}          当高度设置为nil时,预期错误包括“不能为空”,没有错误        './spec/models/coaster_spec.rb:76:在'

中的块(3级)

类似问题:

我有这个测试:

describe 'methods' do

    subject { FactoryGirl.build(:coaster) }

    it "should return a formatted string of coaster name at park name" do
        name_and_park.should eq('Nemesis at Alton Towers')
    end

  end

Coaster.rb:

  def name_and_park
    [name, park.name].join (' at ')
  end

运行测试时出错:

  

2)过山车方法应该返回一个过山车名称的格式化字符串   公园名称        失败/错误:name_and_park.should eq('奥尔顿塔的复仇')        NameError:          '

中未定义的局部变量或方法name_and_park' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_6:0x007f84f4161798> # ./spec/models/coaster_spec.rb:111:in块(3级)

它说无法调用name_and_park但是肯定应该在主题行中制作的Coaster实例上调用该方法?否?

1 个答案:

答案 0 :(得分:2)

它正在“subject”上运行,它可以通过subject方法显式定义,也可以通过将类作为参数传递给describe来隐式定义,在这种情况下是该类的实例被实例化并成为测试的主题。请参阅https://www.relishapp.com/rspec/rspec-core/v/2-0/docs/subject/explicit-subjecthttps://www.relishapp.com/rspec/rspec-core/v/2-0/docs/subject/implicit-subject

至于更新问题的答案,在:speed:length的模型验证中,您有allow_nil: true,这就是为什么这两个测试失败的原因。 validates_presence_of定义的一部分是nil不是可设置值。

关于你的最新问题,我想你可能会对隐含主题的使用感到困惑。如果单独使用should,它确实会默认为subject的任何内容,但如果您自己包含某个主题,就像本案例中name_and_park那样,则不会将其视为默认主题的方法,它必须在当前命名空间中具有定义。在您的情况下,您需要说subject.name_and_park.should ...

在相关的旁边,当您询问特定问题或相关问题并获得答案时,最好使用StackOverflow。由于各种原因,它不适用于正在进行的调试会话。其中一个原因是跟踪原始问题和答案的实质性,连续更新变得乏味。