【问题标题】:Passing a clearer description to RSpec `its` method将更清晰的描述传递给 RSpec `its` 方法
【发布时间】:2012-09-14 14:49:44
【问题描述】:

我是一个 RSpec 新手,但我真的很喜欢编写测试是多么容易,并且随着我学习 RSpec 的新功能,我会不断地重构它们以使其更简洁。所以,最初,我有以下内容:

describe Account do
  context "when new" do
    let(:account) { Account.new }
    subject { account }

    it "should have account attributes" do
      subject.account_attributes.should_not be_nil
    end
  end
end

然后我了解了its方法,所以我尝试将其重写为:

describe Account do
  context "when new" do
    let(:account) { Account.new }
    subject { account }

    its(:account_attributes, "should not be nil") do
      should_not be_nil
    end
  end
end

由于its 不接受 2 个参数而失败,但删除消息工作正常。问题是,如果测试失败,失败示例部分下的消息只会显示

rspec ./spec/models/account_spec.rb:23 # Account when new account_attributes

这并不过分帮助。

那么,有没有办法将消息传递给its,或者更好的是,让它自动输出一条正常的消息?

【问题讨论】:

  • 附带问题,因为它伴随着这个问题:测试 Account has_many AccountAttributes 的最佳 RSpec 方法是什么?

标签: ruby-on-rails testing rspec


【解决方案1】:

你可以定义一个 RSpec 自定义匹配器:

RSpec::Matchers.define :have_account_attributes do
  match do |actual|
    actual.account_attributes.should_not be_nil
  end
  failure_message_for_should do
    "expected account_attributes to be present, got nil"
  end
end

describe Account do
  it { should have_account_attributes }
end

【讨论】:

  • 感谢@zetetic!这更符合我正在寻找的内容:-)
  • @TopherFangio 在我看来,您原来的subject.account_attributes.should_not be_nil 比为每个属性编写自定义匹配器要容易。
  • @Kelvin 你是对的,但是,我只是将其扩展为简单地接受我想要测试的关系的参数,制作代码it { should have_many :account_attributes } 或类似的东西。干杯!
【解决方案2】:

你也可以写:its(:account_attributes) { should_not be_nil }

https://www.relishapp.com/rspec/rspec-core/v/2-14/docs/subject/attribute-of-subject

请注意,随着 rspec 3 的发布,“its”将从 rspec-core 提取到 gem。

【讨论】:

    【解决方案3】:

    看起来一个相对简单的猴子补丁可以满足您的需求。

    查看您正在使用的 rspec-core gem 版本的来源。我在 2.10.1。在文件lib/rspec/core/subject.rb 中,我看到定义了its 方法。

    这是我的修补版本 - 我更改了 def 行和之后的行。

    注意 - 这很可能是特定于版本的! 从您的版本中复制方法并像我一样修改它。请注意,如果 rspec-core 开发人员对代码进行了重大重组,则补丁可能需要非常不同。

    module RSpec
      module Core
        module Subject
          module ExampleGroupMethods
            # accept an optional description to append
            def its(attribute, desc=nil, &block)
              describe(desc ? attribute.inspect + " #{desc}" : attribute) do
                example do
                  self.class.class_eval do
                    define_method(:subject) do
                      if defined?(@_subject)
                        @_subject
                      else
                        @_subject = Array === attribute ? super()[*attribute] : _nested_attribute(super(), attribute)
                      end
                    end
                  end
                  instance_eval(&block)
                end
              end
            end
          end
        end
      end
    end
    

    那个补丁可能可以放在你的spec_helper.rb中。

    现在的用法:

    its("foo", "is not nil") do
      should_not be_nil
    end
    

    失败时的输出:

    rspec ./attrib_example_spec.rb:10 # attr example "foo" is not nil 
    

    如果省略第二个参数,行为将与未修补的方法一样。

    【讨论】:

      猜你喜欢
      • 2012-08-12
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-24
      • 2014-06-21
      • 1970-01-01
      • 2016-05-19
      相关资源
      最近更新 更多