Posted over 6 years ago. Visible to the public. Repeats. Linked content.

Custom error messages in RSpec or Cucumber steps

Sometimes you have a test expectation but actually want a better error message in case of a failure. Here is how to do that.


Consider this test:

User.last.should be_present

In case of an error, it will fail with a not-so-helpful error message:

expected present? to return true, got false (Spec::Expectations::ExpectationNotMetError)


That can be fixed easily. RSpec expectations allow you to pass an error message like this:

User.last.should be_present, 'Could not find a user!'

Now your test will fail with an actually helpful error message:

Could not find a user! (Spec::Expectations::ExpectationNotMetError)

Note that you may also pass a block, if necessary.

Why is this cool?

One might argue why we would want to have better error messages for test expectations when our tests are supposed to be always passing. Well, what if they don't pass at some point? Have you ever had to dig into a test just to find out why it was failing? If that test had actually told what it was expecting, you did not have to do it.

Even more so: Consider an expectation that is actually more complex than the one above. Maybe you are looking at an array of items and want to check only a subset of them. Instead of a simple true/false error message, you could also have a message that shows what the expectation was working on, and what failed:

Found 0 instead of 2 matching events: [] All events: [{"gtm.start"=>1234567890, "event"=>"gtm.js"}, {"event"=>"gtm.dom"}, {"event"=>"gtm.load"}] (Spec::Expectations::ExpectationNotMetError)

And the best thing: Since you are using RSpec expectations in your Cucumber steps most of the time, you can do the same there.


You can't put custom error messages when comparing equality with ==. For that, you might want to use the uglier eql (note that this is close, but not the same as ==):

foo.should eql(23), 'Foo is off!'

Inequality is trickier, and uglier. You might want to wrap your expectation and compare against a boolean, maybe like this:

expect { foo > 23 }.to be_true, 'Foo is off!'

If things get too tricky, you could be better off writing a custom RSpec matcher.

Growing Rails Applications in Practice
Check out our new e-book:
Learn to structure large Ruby on Rails codebases with the tools you already know and love.

Owner of this card:

Arne Hartherz
Last edit:
almost 4 years ago
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Arne Hartherz to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more