将更清晰的描述传递给RSpec`his`方法

时间:2012-09-14 14:49:44

标签: ruby-on-rails testing rspec

我是一个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,或者更好的是,让它自动输出合理的消息?

3 个答案:

答案 0 :(得分:3)

您可以定义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

答案 1 :(得分:1)

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

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

请注意,“它”将从rspec-core提取到一个带有rspec 3发布的gem。

答案 2 :(得分:0)

看起来像一个相对简单的猴子补丁将实现你所寻求的。

查看您正在使用的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 

如果省略第二个arg,行为就像未修补的方法一样。