Why Do We Need Tests?
Seems like a silly question. We want to check if something is working, right?
Let’s dig deeper, though.
At the time of writing, if we’re using test-first, we’re designing interfaces, apply usage scenarios and refactor with a safety net. In test-after, we’re confirming that what we think the software should do, it actually does.
But tests don’t help us only at the time of writing. Once written and run as part of an automated suite, the test changes its initial role, and serves two goals:
- Alert us if something is wrong.
- Help us solve the problem as quickly as possibly.
The first one is obvious. The second one is subtle and easily missed.
Imagine it’s 6 months from now, and the build just broke on the test you’ve just finished writing. Also, imagine you’re on vacation, and somebody else is responsible. Maybe you’re off the hook (for now).
But now someone else needs to solve a puzzle:
What just happened here?
I think we can agree that our brave developer (not the one on vacation) wants to spend as little time as possible on this. After all, she was working on something completely different for a couple of days, committed her code and bang!
Well, guess what: your tests can help her. Let’s go over our inventory of evidence:
- The code changes. For smaller commits, we’ll know pretty quickly, but bigger commits are bigger haystacks.
- The test names. Descriptive test names should tell us the exact scenarios that failed, and what was important about those scenario, including the main reason for the test that is failing.
- The sibling tests. Maybe we have a couple of tests failing, but what about the tests that run through close scenarios? Their results should also direct us to where the problem lies.
- The test code. The final part of the puzzle (if we have to use it) is the test code, but not all of it – what differentiates it from the code of its siblings. All common code is clutter.
This process is called triangulation. In our heads, we try to gather all the pieces of evidence. We want to locate where the problem code is hiding, and understand the effect that caused those tests to fail (and leave others passing).
The more details we leave ourselves (and others), the clearer the breadcrumb trail, it’s going to be easier to solve the mystery. Without it, it’s off to the debugger, Sherlock!
And we all know how Sherlock feels about debuggers.