RSpec be_truthy, exist, or be true?

1 minute read

The documentation for RSpec is amazingly detailed, but sometimes falls a bit short on when to apply certain matchers. In many of the specs that I’ve reviewed, incorrect matchers were used to test for pure Boolean values.

be_truthy and be_falsey

expect(some_evaluation).to be_truthy
expect(some_evaluation).to be_falsey

The matcher be_truthy should only be used when expecting an evaluation to be not nil and not false.

The matcher be_falsey should only be used when expecting an evaluation to be nil or false.

Notice that be_truthy does not actually check for the Boolean value true.

If you have a method that should only be evaluated into a Boolean, do not use these matchers for your spec.

be true and be false

expect(some_evaluation).to be true
expect(some_evaluation).to be false

The matchers be true and be false expect only true and false returned, respectively. This is a straight up value comparison, so use this if your method or evaluation should only return true or false.

exist

expect(some_evaluation).to exist

The documentation for RSpec lists exist right along with be true and be_truthy, though it’s not really related. A spec that matches on exist will only pass if the object has implemented the exists? or exist? methods and the result of its evaluation matches the is_truthy matcher.

This means that passing in true, false, or nil, will fail the test dramatically since none of them implement exist? or exists?.

What’s the Big Deal?

nil

nil is that sneaky value that creeps its way into your code when you don’t expect it. It disguises itself as a missing element in a hash or an unexpected API response value and worms its way though your codebase until it hits that method. That method never expected nil and treats it just like any other value, spitting out a result that should be true or false, but is in actuality nil. The spec for that method uses is_falsey and passes beautifully. Meanwhile, your application breaks and you now have a table column populated with NULL values. Whoops. Good luck figuring out where that happened.

This may seem pedantic and unlikely to happen, but entropy increases as your application grows more complex and these types of problems begin rearing their ugly heads. Especially in dynamically typed languages such as Ruby. So, in most cases, use be true or be false unless you really have a good reason not to do so.