Peter Nixey
Peter Nixey

Reputation: 16565

Is there any way to annotate a test in RSpec?

I often have the problem in RSpec that when I want to loop through a set of conditions, I would like to print something into the test output that explains where I am in them. For instance:

  it "should save & serialize all attributes" do
    @raw_user_attrs.each do |attr_name, value|
      expect( @twitter_user.send(attr_name) ).to eq value
      expect( @twitter_user.raw_attrs[attr_name]).to eq value
    end
  end

The problem with this test is that when it fails, you can't see which attribute caused it to fail, the output looks something like:

1) TwitterUser Raw user loading: data loading should save & serialize all attributes except created_at (auto test)
   Failure/Error: expect( @twitter_user.send(attr_name) ).to eq value
     
     expected: false
          got: nil
     
     (compared using ==)
   # ./spec/models/twitter_user_spec.rb:38:in `block (5 levels) in <top (required)>'
   # ./spec/models/twitter_user_spec.rb:37:in `each'
   # ./spec/models/twitter_user_spec.rb:37:in `block (4 levels) in <top (required)>'

And the problem with this output is that I don't know which attribute it actually failed for.

How can I print a line showing what's actually failed?

It would be nice if I could wrap the test in the loop i.e.

raw_user_attrs.except(:created_at).each do |attr_name, value|
  it "should save & serialize #{attr_name}" do

    @twitter_user.save
    
    expect( @twitter_user.send(attr_name) ).to eq value
    expect( @twitter_user.raw_attrs[attr_name]).to eq value
    
  end
end

This would print the variable into the actual test name. However variables aren't available outside of the scope of the tests themselves and so this doesn't work.

Is there any way to print additional information out what's going on at the time when a test fails?

Upvotes: 1

Views: 798

Answers (1)

MrDanA
MrDanA

Reputation: 11647

You can do that pretty easily for anything other than operator matches (like should be > 1). From the Relish app documentation:

expect(array).to be_empty, "expected empty array, got #{array.inspect}"

So you can tack an expected message on.

Something else you can do in certain situations is loop around the data, then perform its inside the loop, giving them each a good name. Example:

[:method1, :method2].each do |method_sym|
  it "doesn't fail when calling method: #{method_sym}" do
    expect { @object.send(method_sym) }.to_not raise_error
  end
end

Upvotes: 2

Related Questions