I am a "testing fanatic" but I don’t understand test-driven development. Or so I thought.
I have read a few books and numerous blog posts about it, and all of them have one major problem:
The examples are always too simple.
Those examples might be helpful if you write simple text editors or calculators for a living. I don’t do that and the odds are that you are in the same boat with me.
As you might already know, I write web applications with Spring Framework for a living. Let’s find out what kind of problems I had with TDD.
Let's Build a House
When I started working on a new task, I typically followed this workflow:
- Create the domain model objects and the required database tables.
- Implement the repository layer.
- Implement the service layer.
- Implement the web layer.
As you can see, I liked to build things from bottom to top, and I felt that TDD was not a good fit in for this approach. Because I was working my way from bottom to top, it was often impossible to link a test case with a business requirement. This made me feel that a test case had no "real life" value. Its value was purely technical (ensure that that the code is clean and that it works).
And yet, my number one priority as a software developer is find the correct problem and solve it. TDD could not help me to do that when I followed this workflow. Maybe that is one reason why I felt that I had no incentive to use it.
Every time when I tried TDD, I felt that figuring out the test cases before writing any code was mentally draining. Eventually I stopped trying and wrote the tests after my code was done. It was super easy. After all, when my code is done, I knew exactly what should be tested.
This might not be a good thing.
When I built my applications from bottom to top, I missed an essential piece information which often bite me in the ass later on.
What About the Requirements?
A few days ago I was walking back to home from gym and thinking about this tweet by Kent Beck:
tdd is a great excuse to think about the problem before you think about the solution
Suddenly it all made sense to me (working out seems to be good for your brain). I realized that TDD made feel confused because my workflow was flawed. Instead of thinking about the problem before the solution, I worked my way up from the solution to the problem.
This means trouble.
If we think about the different layers of a web application, we notice that the layer which is "closest" to the solved problem is the web layer. It seems almost obvious that this is the layer where we should start our work.
Let's think about what happens if we flip my old workflow around and start working from top to bottom. This means that
- Each layer specifies the requirements for the layer below it. This means that we don't write code which is not required. Of course, nothing is final. Requirements might change and we have to change our code. However, this approach eliminates changes caused by misunderstanding the requirements.
- We can concentrate on the requirements and transform them into test cases. When all test cases pass, we have a software which fulfils the given requirements. Also, since we understand the requirements of a specific component, it should be a lot easier to figure out the required test cases even if we haven’t written any code yet.
The more I think about this, the more sense TDD makes to me. I have already tried this “new” approach with TDD and it looks really promising. The most notable improvement is this:
Figuring out meaningful test cases is no longer hard. It is easy.
Why Should You Care About This Shit?
If you are not interested in challenging yourself, you should stop wasting your time and STOP READING NOW. I have already wasted enough of your precious time.
I have noticed that sometimes developers think that the source code of the application is the most important deliverable of a software project.
The problem is that source code has no value unless we can prove that it
- Solves the right the problem.
- Works as expected.
That is why writing automated tests is important.
It saddens me to see that many developers are constantly seeking ways to improve their coding skills but only a few of those developers are looking for new ways to write tests.
Wake up people! Tests are code too!