One of the testing questions I commonly get is about Shoulda matchers. People ask if I use Shoulda matchers and if Shoulda matchers are a good idea.
I’ll share my thoughts on this. First I’ll explain what Shoulda is, then I’ll explain why the only Shoulda matchers I use are validation matchers.
What Shoulda is
If you’re unfamiliar with Shoulda matchers, the premise, from the GitHub description, is: “Shoulda Matchers provides RSpec- and Minitest-compatible one-liners to test common Rails functionality that, if written by hand, would be much longer, more complex, and error-prone.”
A few examples of specific Shoulda matchers are
validates_presence_of (expects that a model attribute has a presence validator),
have_many (expects that a
has_many association exists), and
redirect_to (expects that a redirection takes place).
I like the idea of a library that can clean up a lot of my repetitive test code. Unfortunately, the majority of Shoulda matchers only apply to the kinds of tests I would never write.
Test behavior, not implementation
To me it doesn’t make much sense to, for example, write a test that only checks for the presence of an Active Record association and doesn’t do anything else.
If I have an association, presumably that association exists in order to enable some piece of behavior, or else it would be pointless for the association to exist. For example, if a
has_many :posts, then that association only makes sense if there’s some
So there are two possibilities in light of testing that the
has_many :posts. One is that I write a test for both the association itself and the behavior enabled by the association, in which case the test for the association is redundant and adds no value. The other possibility is that I write a test only for the post association, but not for the post behavior, which wouldn’t make much sense because why wouldn’t I write a test for the post behavior?
To me it only makes sense in this example to write tests for the post behavior and write no tests directly for the association. The logic of this decision can be proved by imagining what would happen if the
has_many :posts line were removed. Any tests for the post behavior would start failing because the behavior would be broken without the association line present.
Why validation matchers are different
I mentioned at the top of the post that validation matchers are the only Shoulda matchers I use. The reason I do use Shoulda matchers is because validations aren’t just a means to an end, they’re an end in themselves. In other words, validations are a feature.
The alternatives to using Shoulda matchers to check for validations are to not write validation tests at all or to write really repetitive tests for validations. Both those alternatives seem bad to me, so Shoulda matchers it is.