Lost in the Source #3
There’s something I want to talk about that may be a little controversial. When learning to code, you’re taught that DRY (Don’t Repeat Yourself) is a great principal to follow. In a nutshell it means that code shouldn’t be repeated throughout your codebase. There are a few reasons you don’t want to repeat yourself: it’s tedious for you, it’s confusing for people reading your code but most importantly, it can potentially cause performance issues in your app, or could be more insidious in nature with things being overwritten or reset unintentionally. The way to keep things DRY is to abstract the common code into one place and require or call that code where it’s needed (read my article on keeping CSS DRY here).
This is a good idea and something I’ve tried to follow during the duration of my development career, so imagine my surprise when yesterday, I tried to apply the same rule to my tests and my mentor stopped me. I have three feature tests that look like this:
In each test I’m creating the link and I’m visiting the root_path so this bit of code below is repeated three times:
This is contradictory to everything we know about DRY, obviously. So why did my mentor stop me from moving this repeated code into one file or before block that gets required in the necessary places?
- Tests should be independent: Your tests shouldn’t really be dependent on other things running/working, for them to work themselves. There are instances where you’ll need dependencies like in the use of factories but one tests shouldn’t have to run & pass in order for another test to run & pass. This means that if there is a failure, it’s easy to isolate the problem to the correct place. If tests become dependent, you’d probably also need to test the dependency to make sure that works as it should and then things become excessive and complicated.
- Tests are easier to read: Having that repeated code block in the tests makes it easier for those who are new or unfamiliar with the codebase, to read the tests and understand what’s going on without getting lost in the codebase.
- There is no real added benefit to DRY in tests: In the context of testing, DRY doesn’t really have any added benefit. The app is separate from the tests so app performance isn’t affected, your test suite may slow down but I’d argue that if you were really going to DRY up your tests you’d have to test dependencies which would add bloat to your test suite anyway.
I love DRY, I might even be a little obsessed, but the point of DRY is to ease the load off of the application and the developer, it means you’ll be updating fewer places when changes happen, and the app will be faster and more dynamic. The moment DRY creates more work than just repeating yourself, it loses its benefits.