Just kidding. Write unit tests. Always. For everything. Period.
This blog article could end here. It tells you everything you need to know: Testing is good. Do it! However, there are many developers out there who do not write tests or even hate it. This is due to a couple of misconceptions, the most famous being:
- "We've got no time for testing"
- "I know that my code works"
- "I hate maintaining all those crappy tests"
Dysfunctional teams and bad development practices are spread so widely that many people do believe it was actually true that tests cost time, are hard to maintain and do actually only show the obvious. Consequently they are deemed as being useless, redundand, expendable or annoying.
Being in this testing hell myself for a long time, I started to realize that something must be done about this. Should we go ahead and simply throw those tests away? Actually that would make sense in some projects, because those bad tests do not produce any value for the project.
Or, we could go with craftsmanship, which implies that well-crafted tests should be part of every developers mindset, not just because blogs, books or Sonar tell you to do so, but because they can be exploited as a tool to write high quality software themselfes. High quality software decreases costs for operation, maintenance and future development a lot and therefore should be the ultimate goal of every development effort.
TDD To The Rescue
How is that, you might ask. Test Driven Development is the answer. You can read all over the Internet about this approach. There are advocates and adversaries. In a nutshell it works like this:
- Write a failing unit test that tests one thing and one thing only (RED)
- Write just enough business code to make the test pass (GREEN)
- Refactor to clean up the mess (REFACTOR)
- Repeat until done
For this to really make sense and produce value, tests must comply with a couple of characteristics, known as FIRST:
- Independent / Isolated
- Self Verifying
Keeping this in mind, we can go on and deconstruct "reasons" for not writing tests.
No Time For Testing
Since writing a test is now part of each and every development effort there cannot be no time for testing. Saying "We've got no time for testing" would be like saying "We've got no time to develop" which, if true, points to the real problem.
Furthermore, the tests do also not slow you down. In fact, they are speeding things up, because
- Fast tests are, well, fast.
- By having the tests at your side, you will notice errors early.
- They tell you exactly when to stop. No gold plating or over engineering, no additional code to maintain.
- Tests following FIRST are easier to maintain which saves time.
I Know That My Code Works
That may actually even be true. At least when the code has been freshly written. But what about a refactoring? How do you know the code still works? What about next week? Will you remember what it does and why? What about your colleagues? How should they know?
You do write tests in the first place not to test if things work, but to specify how things are supposed to work. Now and in the future. You do make functional changes to tests only because the specification has changed. This will make a test fail and this is the only reason why you would make functional changes to the code under test. If you do not write the test first, how do you know which change to implement where? How do you know your change has the desired effect? How will your colleagues know?
I Hate Maintaining All Those Crappy Tests
I am right there with you. We've all been there. We all know those "What the hell were they thinking?" moments when it comes to maintain other people's tests. The reason behind this is:
- You need to test code that was not designed to be test friendly
- This makes test setups large, complicated and brittle. The execution opaque.
- Test code is not considered production code and consequently does not comply with quality rules
- This makes test hard to read and understand due to poor naming and design.
When maintaining test driven code, you are maintaining a code base that does not know of any differences between production and test code. The same quality rules apply for every one and every line. Test code is of course subject to refactorings.
Writing tests first helps you to find just the right design. Code has only been written to make an existing test pass, thus making the design automatically test friendly.
Seeing Is Believing
I am afraid but everything comes with a price and for you to actually take benefit from TDD you'll need to get your hands dirty:
- Do some research and read a lot
- Practice together with others in coding dojos or on your own with code katas
At the beginning, I was very sceptical of TDD. The turning point was when I excercised the WordWrap Kata. By using TDD I realized that I was already done and had a simple solution while I knew that "my" solution would have been much more complex if I would have done it without TDD. In addition I might have never come up with the idea to solve the task by the help of recursion. I realized how bad my usual testing habbits where and how badly this influenced the design of my production code.
itemis Can Help You Out
Of course, being an agile consulting company, itemis does offer coding dojos on a regular basis and a TDD workshop. I had the opportunity to take part in it and I can tell you: It was well worth the effort. Hard but very rewarding. Many thanks to Christian Fischer who is a very passionated and skilled workshop host.
The workshop provides 3 days of training and many practical exercises. At the end you may take on the accompanying iSQI TDD exam which if passed grants you the certificate iSQI® Certified Agile Test Driven Development.
So, how about getting out of testing hell? Sounds interesting? Just contact us! We would be glad to hear from you.