Test Driven Development – But Why?

Everyone knows that tests are needed, but do you know really why? What are the benefits?

In the beginning of our projects, we are in a green field where every code we write is nice and works, the speed of the project is high, the number of bugs is low and developers and clients are happy.

As the project advance the code start to get messy, every time we have to make a change is harder, in more places and force us to hack our own code or add some nasty code.

After a few months our code is rotten, becomes rigid and fragile. The speed of the team decreases and the number of bugs increases. The developer is scared to introduce changes to the code and to refactor because he doesn’t know if he will break another functionality, all the bug fixes or changes to existing code are small hacks.

So the developer is scared to touch the code because it is too fragile, he needs some kind of protection that he doesn’t break any functionality. This protection are the Tests.

Imagine to have a suite of test that could detect the vast majority of the bugs that could be run just with the click of a button in a few minutes… this is what TDD aims for.

What is TDD?

It is an Agile methodology which consists in letting our tests drive the development of the product writing them first to force us to write the exact code that makes those test pass.

But why?

Reduce the debug time

If we have a complete suite of tests we keep writing and updating them and running quite often, every time there is a bug, this bug will appear in the test as an error, so is already spotted just when it was created, and it will be easier to fix since it is located in the code that we just wrote so it is fresh to our mind. You don’t have to spend hours debugging through the whole call stack to check when, where and about what is the bug.

Living documentation

Normally when we try to use a new API we go directly to the examples of code that shows how to use the API, and sometimes we even copy & paste the example and try to tweak it to use it in our code. So well, the Unit tests are those examples. If you have a complete set of Unit test in your product you only need to take a look at them in order to know how your code works.

You have in your set of tests an example of every possible way to use your code. Is the perfect documentation that is reliable and is always updated.

The courage for change

Thanks to the suite of unit tests that covers most of your code you can be sure that your code is working, this will eliminate the fear of the developer to change anything allowing him to clean the code and refactor freely. Tests stop the code from rotting.

Why to write tests first?

Writing tests first makes the production code testable. Ok that’s obvious but what is de benefit? If the production code is testable it means that it is decoupled, if you can test a part of the production code by separate in one unit test then that part is decoupled from the rest of the components. The more decoupled the system is the more flexible and extensible is.

You get a better design just by writing test first.

Normally if you write your tests after writing your production code they won’t be as complete as if they were written first because you already know your code works and it is boring to write only tests, sometimes you are tempted to take shortcuts and you miss some tests.

If you write the test first you are writing code to pass those test, so every line of production code is covered by a test. You trust your test, they are more complete than if you write them after.

And how do we do TDD?

It consists in a 3 phases cycle, known as red, green, refactor. This cycle must be very short and the iterations must be quite fast in order to not be much time outside of the green phase where all your code is working.

There are 3 phases:

Writing a failing test first.

Writing the production code to pass the test.

Refactoring the production and the test code.

In the Redphase we write a unit test that fails that will force us to write the production code that we want to write.

In the Greenphase we are able to write the production code to make that failing unit test pass. We write no more no less.

In the Blue phase, when our production code works as desired, we clean the production and the test code, making it more sustainable, extensible, removing duplication, in other words, we clean the code.

The 3 laws of TDD.

TDD is a discipline, as any discipline it has a set of rules that for the beginners can sound a little extreme, but with time they will become more and more logical. Here are the 3 Uncle’s Bob TDD rules, read them well and understand them well:

• You are not allowed to write any production code unless it is to make a failing unit test pass.

• You are not allowed to write any more of a unit test than is sufficient to fail; and compilation failures are failures.

• You are not allowed to write any more production code than is sufficient to pass the one failing unit test.

Follow these 3 rules and they will force you to write alternating between test and production code in short time periods and you will always have production code that is passing all the tests or at least was not long time ago.

At the beginning coding in the TDD way will be slow and hard, but with time you will change your mindset and you will be automatically thinking about features that your code should do, instead of solutions, writing tests for it instead of implementing the production code directly and thinking how to write your production code to be easily testable and decoupled from other functionality.

Most of the information was obtained from the teachings of Robert C. Martin Aka Uncle Bob in his videos. You can download his videos at CleanCoders.com and follow his company blog for more interesting articles 8thLight Blog.

9 thoughts on “Test Driven Development – But Why?”

Doesn’t
“You are not allowed to write any production code unless it is to make a failing unit test pass.”
and
“You are not allowed to write any more production code than is sufficient to pass the one failing unit test.”
mean the same thing? Both mean that one should only cover tests in their code, so there are essentially only 2 “laws” not 3.

They are 2 different points, the first, “You are not allowed to write any production code unless it is to make a failing unit test pass.” wants to say that every production code that you write is has the purpose of make the failing unit test to pass.
The second, “You are not allowed to write any more production code than is sufficient to pass the one failing unit test.” means that when you are writing that production code, you should write only, no more and no less, to make this single test pass. This means that you cannot think in advance and write the code that will pass the next test you will do, must only make pass the failing test that you are writing the code for.

There are 2 different areas covered. The first rule is about the behavior (writing test first) and the second is about scope (writing only the code that is sufficient to pass, no more).

I hope I solved your doubt. If not please feel free to ask more question! 🙂

“You are not allowed to write any production code unless it is to make a failing unit test pass.” – this implies that:
1. Test come first, coding next (no coding before writing tests)
2. No coding that doesn’t cover tests (excessive code doesn’t help a test to pass)

“You are not allowed to write any more production code than is sufficient to pass the one failing unit test.” – implies that:
1. Test come first, coding next (to write code that covers a test this test must exist)
2. No coding that doesn’t cover tests (explicitly stated that no more than sufficient)

But this is only a semantic problem, not important. The article as a whole is great with maybe a little exception for the part where decoupling is mentioned.

Thanks for the congratulations!
Both sentences implies your points, yes, but not only, you are making a generalization about what the sentence wants to express.
The first rule doesn’t forbid you to write code that makes that test pass but also makes the next test pass, or more than one test pass.
The second rule “You are not allowed to write any more production code than is sufficient to pass the one failing unit test.” is forbidding explicitly that you cannot write more code than the necessary to make exactly that failing test pass.
Of course you can mix both rules into one single sentence but the rules have different purposes that’s why I think the author wanted to keep them separate.

Roi Otero, yes – “The first rule doesn’t forbid you to write code that makes that test pass but also makes the next test pass, or more than one test pass” – this is what progress in TDD is about, you do one thing then next one.
And yes – “The second rule […] is forbidding explicitly that you cannot write more code than the necessary to make exactly that failing test pass” – but it obviously doesn’t forbid you to skip to another test.

The problem is you have two boxes with a mix of oranges and apples, you pick an apple from one box and an orange from another, and conclude the boxes are different.
Just because someone stated two synonymous sentences as different it’s not justified to repeat his/her error 😉 Please, reread my previous comment.

All in all, it’s just a semantic problem, it doesn’t make the article wrong, it just makes harder for a newcomer to understand the point of TDD.

I have to disagree with your metaphor, If we have a box that contains apples and another that contains oranges, both contain fruits, and you can call them both fruit boxes but you can still call them Orange box and Apple box.

I agree that the rules could be rewritten in a easier way to be more understandable, even just say it as one sentence and could be clearer. I think they were written like this because the author wanted to make explicit the 3 most important points at what he was looking at when doing TDD.

I think that the second rule has some extra value that the author though it was enough to have a separate rule for it. This value is to make that test and only that test to pass, it provides a little clue about the separations of concerns when writing the tests. One test = one failing reason.

Thanks for sharing your thoughts! Its nice to hear more different points of view!

Roi, “two boxes with a mix of oranges and apples” – two boxes where both have oranges and apples inside not two boxes where one has oranges and the second one apples 😉

Yes, if you if the rule states that overdoing one functionality results in implementing another then this is a problem with separation of concerns at design part, but at the moment the tests are already done and code needs to be written it just cannot be helped. That’s a problem with design not realization of TDD. If this rule was about separation of concerns then there are easier ways to say that… and TDD is possible without proper separation of concerns. Even though they come in pairs they’re separate ideas – separation of concerns is not a part of TDD but a result. Though indeed, good separation of concerns at design level definitely helps TDD. Isn’t that right?

I was trying to explain my point with a similar but different metaphor like yours, wasn’t trying to explain yours.

I think we both think more or less the same about TDD and its rules/way to use it, I was just defending the authors position and read his 3 sentences in a way that makes sense to be 3 and you read it in a way that makes sense to be 2, it is just matter of semantic as you said he he.