In Defence of Shoulda Matchers
Merryn Hurley Rawlins
I recently caught an interview with Jason Swett, author of The Complete Guide to Rails Testing, on my go-to Rails podcast, Ruby For All (give them a listen here!). Jason is a leading voice in Rails testing, and notably, he doesn't use Shoulda Matchers. There’s a pretty strong argument here based on the ‘test behaviour, not implementation’ mantra.
The Case Against 🛑
Take the classic example of a has_many association in the User class to Posts. The Shoulda Matcher skeptic might argue that testing this association directly is either redundant (if we're already testing the behaviour enabled by the association) or pointless (if we're not testing the Post-related behaviour). In sum, with appropriate behaviour-centric testing, we shouldn’t need Shoulda Matchers. I certainly see merit in this argument. However, I'd like to cautiously throw my hat in the ring in defence of Shoulda Matchers.
Validation and Peace of Mind 🧘♀️
I love listening to Ruby For All because it is made for juniors that love Rails but don’t necessarily have a wealth of experience. For juniors, Shoulda Matchers make checking model associations and validations simple and quick, super handy for both building and tweaking your code. Plus, Shoulda one-liners make your tests a lot easier to read, which is a win for everyone looking at and reviewing your code. More generally, in sprints where core feature development follows after necessary migrations, Shoulda shines. Mistakes happen, and you want to discover that something has gone awry in your database design as soon as possible.
Onboarding and Understanding 💡
Another advantage lies in onboarding. The concise overview Shoulda Matchers provides of model relationships and validations can help newbies understand codebases faster. This can make a world of difference in a team environment.
Testing Behaviour After All 🧪
In the context of validation matchers, Shoulda is testing behaviour (though, to be fair to Jason, not particularly high-level behaviour). When we use validate_presence_of, we are essentially asserting that our model behaves a certain way - it fails validation when a required attribute is missing. Likewise, Shoulda Matchers' validate_uniqueness_of matcher aligns neatly with behaviour-driven testing. This matcher works by checking against existing model instances (or creating a new model instance if necessary) and ensuring an additional instance fails validation when attributes duplicate those of a pre-existing record. Once again, this shows us that Shoulda can do more than simply check your code - it actually makes sure your model is behaving as it should.
Depending on how closely you follow the behaviour-driven testing philosophy, you may find more or less use for Shoulda. Still, as a Junior dev trying to get comfortable in a relatively wide range of codebases, I’m certainly glad it’s part of my toolkit!
- Ruby on Rails
- Testing
- Shoulda Matchers
- Ruby For All