TL;DR: using "
be" (or "
equal", which does exactly the same thing) produces distracting and usually meaningless extra verbiage, while "
eq" (or "
eql", which is a little different but close enough for this purpose) does not.
Frex, if you are sending an HTTP request and expecting to get back the OK status code, you might say:
This will work fine, and so long as the status actually is 200, then all is right with the world.
expect(response.status).to be 200
The minor, trivial, nitpicky, but still a bit annoying, problem, comes when the status is not 200. Sure, you'll still get a test failure... but you'll get some added little distractions, the bold parts here:
All you really needed is this:
Failure/Error: expect(response.status).to be 200 expected #<Fixnum:401> => 200 got #<Fixnum:1001> => 500 Compared using equal?, which compares object identity, but expected and actual are not the same object. Use `expect(actual).to eq(expected)` if you don't care about object identity in this example.
(Okay, granted, you didn't really need to know it was compared using "
expected: 200 got: 500 (compared using ==)
==", but still, that's not too bad... at least it's a lot less distracting verbiage to wade through than the prior message.)
(And okay, granted, four short lines of additional feedback aren't that much of a pain... but still, they add up. If you're new on a project with lots of failing tests, as I am now, it can make it harder to wade through all the failures and see which ones actually mean anything.)
So how do you get rid of it? You might try using "
==" instead of "
be", especially if you're used to RSpec's older "
should" syntax rather than the new "
expect" syntax (which I'll ass-u-me you are now using)... but then you'd see:
But despair not, dear reader, all is not lost! It's still very simple. Instead of "
Failure/Error: expect(response.status).to == 200 ArgumentError: The expect syntax does not support operator matchers, so you must pass a matcher to `#to`.
be", use "
eq". Then you get:
As you may recall from my Ruby Gotchas presentation, there are several ways to compare things in Ruby:
Failure/Error: expect(response.status).to eq 200 expected: 200 got: 500 (compared using ==)
==" compares the value, without regard for the actual class(es) of the objects. So, frex, "
1.0 == 1" is
true. This is what RSpec uses when you say "
eq" (or "
==" in the older syntax); hence the message "
(compared using ==)".
.eql?" compares the value and class! So, "
1.0.eql? 1" is
.equal?" is object identity. That is, even if two things have the same value, and the same class, if they're not the exact same object, they are not "
.equal?". One of the oddities of the Ruby object system is that an object is created for each new unique Float value, so the result of:
x = 1.0 y = 1.0 x.equal? y
true! However, if we use a more complex class, like
String, we can see that "
'foo'.equal? 'foo'" is
expect(response.status).to eql 200"? Pretty much the same thing, just now it says "
(compared using eql?)".
But... if you take it one step further, and use "
expect(response.status).to equal 200"... then you're back to Square One. That shouldn't surprise any of you who paid close attention to the original verbose error message: it told you that when we used "
be", it "
Compared using equal?, which compares object identity".