Other reasons for TDD: Baby steps, ROI, Evil Manager Syndrome and Watching the watchmen
Dan Lebrero
Posted on February 27, 2019
Perhaps the world does not need another “X reasons for TDD”, but I find most people miss these four very important reasons for following a test-first approach:
- Baby steps
- ROI
- Evil Manager Syndrome
- Watching the watchmen
Baby steps
The TDD (Test-driven Development) workflow encourages you to make progress in small baby steps. With this workflow, you feel like a small meerkat that every few steps stands up to check its environment.
Maybe not the fastest way to reach your destination but, without a doubt, the safest. But as we do not run the risk of being eaten, what does it mean for us to be safer?
After each small change, we check that no bug was introduced. And if a bug is introduced, it is obvious when and where the bug was introduced: in the last tiny step.
Finding the bug becomes trivial. And bugs are the second worst time wasters in software development:
- First, you spend time writing it.
- Then somebody has to review the bug.
- Then you have to release it to production.
- Your client has to report it.
- You triage the impact.
- Your manager has to prioritize it.
- You have to fill up some JIRA issue.
- You explain it to your QA.
- You have to debug the code, code that by now is probably completely alien to you as probably it has been days or weeks since you wrote it.
- Then you fix it.
- Somebody reviews the fix.
- And at last, you release the fix to production.
So, paradoxically, doing baby steps and being safer can also mean going faster, depending on how many bugs you write.
This principle is in fact exactly the same as the “Small batches” principle in Continuous Delivery.
Moral: if you don't write bugs, do not waste your time writing tests.
How small should the baby steps be?
As small as possible, but its lower limit it going to depend on how fast your test suite is:
Even if you try to be very disciplined about running your tests after every small change, if your test suite is slow, you will end up making your change batch size bigger, just to avoid the pain of waiting.
Hence, if you want to influence how often the tests are run, you need to make sure that they run very fast.
Return on Investment (ROI)
A test suite is an investment and, as with any investment, you want to have a high positive return on investment (ROI). ROI can be calculated as:
ROI = (Gain from Investment - Cost of Investment) / Cost of Investment
The costs of a test suite are pretty obvious: time to build and maintain it. There is also the ongoing cost of running it (another reason why faster test suites are better).
There are several benefits to a test suite, but we can sum them all up as time saved while making changes.
So the ROI of a test suite can be calculated as:
ROI = (time saved - time spent) / time spent
If we plot the ROI (in red) with a test-last approach when building a new feature, we can imagine something like:
If you never ever touch that part of the codebase again, the tests are the worst of your investments, as it will not start to pay off until you start making changes again in that particular area of the codebase.
Let’s compare it with a test-first approach:
Tests start to pay off immediately, as you are actively changing the codebase covered by those tests.
Moral: if you write a test, write it first. Note the highlighted if in the previous statement.
Evil Manager Syndrome
"I’m not given time to write tests" is probably one of our favorites excuses when we are questioned about why our code coverage is less than ideal. It is not your fault, it is your evil manager’s fault:
Manager: “We have to deliver yesterday!”
Team: “But we haven’t finished yet!!”
Manager: “Let cut some corners!!!”
Team: “Let's skip writing the tests until we have time!!!!”
Manager: “Awesome! You are a fantastic team!!!!!”
And this is how typically the spiral to the crying rewrite starts:
- As you have little tests, you cannot refactor.
- As you cannot refactor, your codebase starts to accumulate garbage.
- The more garbage in your codebase, the longer features take to be implemented.
- The longer features take to be implemented, the more time pressure there is.
- The more time pressure, the fewer tests.
And this completes the downward spiral that always ends up with us, developers, crying for a complete rewrite.
Let’s see the same situation but when doing test-first:
Manager: “We have to deliver yesterday!”
Team: “But we haven’t finished yet!!”
Manager: “Let cut some corners!!!”
Team: “What features can we cut?!?!?!”
Manager: “Cutting features??? Do not write any tests!!!!!”
Team: “We already wrote them!!!!!!”
Manager: “Bastards!!!!!!!”
And then follows a long conversation about what features to trim, which your manager hates. Welcome to agile.
Watching the watchman
Seeing a test fail is the test that tests if the test tests what is supposed to test.
Or in simpler words, how do you know that your test doesn't have any bugs? Who watches your watchmen?
If you write a test first and you see it fail, there is a strong indication that there is some piece of production code, some logic, that is not there.
If you write the test and you never see it fail, you don’t know if it is because you’ve ready implemented a feature, or because you forgot on an assert in your test or the setup code is not correct.
Moral: Writing your tests first keeps the watchmen honest.
Test-first all the things?
But no matter how many reasons you have, when you present this test-first approach, most of the time you get the ominous answer: “How can I write the tests first if I don’t know what I am going to build?”
And as any experienced TDD developer will tell you, that is BS ... but not always. We will see next time when is and when is not TDD the best approach.
Posted on February 27, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
February 27, 2019