Saturday, October 31, 2009

Why TDD Rather Than Traditional QA's Writing Tests

First, I describe what is TDD. Then, I present a story that lead me to writing this article.  But if you don't care about stories, just skip to Conclusion and Resources

What is TDD?
I'll describe TDD not with my own words but with a few selected excerpts from this resource:
  • The practice of maintaining automated unit test suites has gained widespread acceptance over the past decade to the point where most developers today either engage in some amount of test writing or at least feel bad for not doing it.
  • To prevent regression, developers must provide a set of tests that exercise an application top-to-bottom and end-to-end (front-end to back-end), but anecdotal evidence suggests that even automated tests covering as little as 50% of the code can effectively guard against regression in many applications.
  • Competent developers either conform to a test-first discipline in which small test harnesses are built to exercise an API before the API itself is even implemented, or else employ a code-a-little-test-a-little (CALTAL) approach in which each unit of code developed is tested immediately after its compiled.
  • Most build systems, such as ant, provide direct support for running test suites as part of the application build process, and continuous integration systems, such as Cruise Control or Hudson, kick off such builds automatically each time code is committed to the team's version control system

Recently, I ran into project OpenSatNav. It's an open-source version of AndNav2, that is navigator application for Android OS based on OpenStreetMap. Great project, still pretty young, but dynamically expanding. I watched a few issues being fixed by the developers involved, and noticed that the process of findind a solution was a bit erratic. There were several attempts to guess a solution, and guesses were not perfect, but then there were a few better guesses.  Some NullPointException bugs cropped out after a few days and were fixed. Still, some issues were reported, but never reproduced, so by the token "it doesn't show the problem anymore, so let's close this issue", the issue has been closed. What was obvious to me, is that the solution is not necessarily correct. The testing was done manually and without even any systematic approach.

Spring into Action
It was obvious to me that what was definitely missing, was the automated testing, especially unit testing. I tried to step in and encourage unit testing. The idea of TDD, or any unit testing that I proposed several times was for the project team like a fairy tale about a bad wolf. But the developer team and the project lead were friendly and not exclusive.The lead-developer on this issue, responding to my requests, did include a well defined test-scenario with the fix code. I thought: it's not bad, I'll step in and write a unit or functional test for this fix. I have experience with TDD for Android, Java, GWT and Flex projects.

It took me time (I have a full-time job and four children ages 4 - 19, plus, I took this as an opportunity to review the currently best practices for testing for Android OS), but finally I got to writing the test. And here's what I have found, which may be very well what also you experience is in this matter.  While writing a unit or a functional test for your own fix or new feature is a fun and a relatively straightforward activity, writing a test for a code written by someone else, is neither much fun nor simple. You end up reverse engineering the whole part of the system that surrounds the part where the fix was made.

Simple. Write your own tests. This, was for me always fun and an enlightening experience. And, I think, my design and coding have improved because of the tests I wrote. Tests for my own fixes.  Tests written immediately after I have written the code (CALTAL), or even just before I have written the code.

The following are useful for getting quickly to speed with TDD, esp. for Android OS development:

No comments: