In the book Java Extreme Programming Cookbook , Eric M. Burke and Brian M. Coyner describe the top reasons why one should do unit testing and why. The book itself may be a bit dated, the reasons described in it are still valid today.
- Tests Reduce Bugs in New Features
- Tests Reduce Bugs in Existing Features
- Tests Are Good Documentation
- Tests Reduce the Cost of Change
- Tests Improve Design
- Tests Allow Refactoring
- Tests Constrain Features
- Tests Defend Against Other Programmers
- Testing Is Fun
- Testing Forces You to Slow Down and Think
- Tests Reduce Fear
Testing Makes Development Faster
In this article i would like to focus on this last reason. For most developers this doesn’t seems logic and even for management people it seems a bit far fetched. So is this statement true?
Well for me the answer is not straightforward. It strongly depends on the context. In fact when i don’t have to work with other people I can produce clean good code fast with a limited set of unit tests. These unit tests are often not really unit tests but just sanity tests to verify that the system behaves like i want it to behave. Even when the system becomes bigger and bigger (+10.000 loc) I can still add functionality ‘s fairly easy, I don’t miss unit tests. The reason why is because i know the system / codebase very well, hence i wrote it. So in this situation i would say that testing would only slow me down.
However, everything changes when you turn to enterprise applications. You’re no longer working alone and the code you write will outlive the time you’re working on the project. Suddenly you have to use code that isn’t your own, code that you often would like to change because it doesn’t do exactly what you want, but when you dive into the code you notice that the impact would be rather big so you don’t change, you just look for a work around. Sounds familiar?
When developping with no unit test i usually see 3 different phases where the development speed changes significantly
- Limited setup.
- When the frameworks you want to use are in place your starting to produce new features very fast.
- When the system becomes more complex or more developers start working on the project you’ll become less efficient because you’ll loose time undertanding & verifying the system.
When you are writing unit tests this curve becomes different (see the blue line). Your initial phase will demand more setup (you’ll need a test framework, datasets, a CI,..). When you start programming your loosing time creating unit tests. However in the third phase a bigger codebase or other developers won’t slow you down, you have your tests and their tests to prove the system works. Your productivity won’t drop over time as it would if you weren’t writing tests.
What if the codebase of the other person was provided with a substantial set of unit tests. A set that would say : “if all tests succeed, I guarantee that code still does what it should do” and if a tests fails it exactly shows you where some behavior is broken . This is great, i could change the code to add things I want without wandering if the code still does what it should do, i just run the guys tests and i have faith. This is a great world to be in as a software engineer. I noticed that i could advance way faster than if this software engineer wouldn’t have provided me with these tests.
I have “faith”.
This is probably the most important reason why unit tests speed up development in a enterprise context.
I can thrust that everything still works if all tests pass. If tests fail they will point out exactly where the problem lays.
However to be able to have this kind of faith you have to have a high unit test coverage and good unit tests. When these conditions are respected you’ll find yourself in a situation that the effort for adding new functionality ‘s is almost independent of the size of the application and that in the long run it will speed up development.
What’s a high unit test coverage? As starting point I usually say > 75%, things like exception handling and gui component positioning aren’t that crucial when it comes to unit testing. What about testing your domain objects or value objects or data transfer objects or…? Often people argue that these things (simple pojo’s or javabeans) shouldn’t be unittested because “it’s too simple to break” . I don’t completely argree with this statement, you should test it’s correctness but you should find an efficiant way of testing these things. More on that in a next blogpost.