What is Test Driven Development (TDD)?

TDD is an iterative software development process where you first write the test with the idea that it must fail.
This is a different approach to the traditional development where you write the application functionality first and then write test cases. The major benefit of this approach is that the code becomes thoroughly unit tested (you can use JUnit or other unit testing frameworks). For JUnit refer Q14 on “How would you go about…” section. TDD is based on two important principles preached by its originator Kent Beck:

  • Write new business code only if an automated unit test has failed: Business application requirements drive the tests and tests drive the actual functional code. Each test should test only one business concept, which means avoid writing a single test which tests withdrawing money from an account and depositing money into an account. Any change in the business requirements will impact pre and post conditions of the test. Talking about pre and post conditions, following design by contract methodology helps achieving TDD. In design by contract, you specify the pre and post conditions that act as contracts of a method, which provides a specification to write your tests against.
  • Eliminate duplication from the code: A particular business concept should be implemented only once within the application code. Code for checking an account balance should be centralized to only one place within the application code. This makes your code decoupled, more maintainable and reusable. I can hear some of you all saying how can we write the unit test code without the actual application code. Let’s look at how it works in steps. 
    • The following steps are applied iteratively for business requirements.
      • STEP: 1 write some tests for a specific business requirement.
      • STEP: 2 write some basic structural code so that your test compiles but the test should fail (failures are the pillars of success). For example just create the necessary classes and corresponding methods with skeletal code.
      • STEP: 3 write the required business code to pass the tests which you wrote in step 1.
      • STEP: 4 finally refactor the code you just wrote to make it is as simple as it can be. You can refactor your code with confidence that if it breaks the business logic then you have unit test cases that can quickly detect it.
      • STEP: 5 run your tests to make sure that your refactored code still passes the tests.
      • STEP: 6 Repeat steps 1-5 for another business requirement.

To write tests efficiently some basic guidelines need to be followed:

  1. You should be able to run each test in isolation and in any order.
  2. The test code should not have any duplicate business logic.
  3. You should test for all the pre and post conditions as well as exceptions.
  4. Each test should concentrate on one business requirement as mentioned earlier.
  5. There are many ways to write test conditions so proper care and attention should be taken. In some cases pair programming can help by allowing two brains to work in collaboration. You should have strategies to overcome issues around state of data in RDBMS (Should you persist sample test data, which is a snapshot of your actual data prior to running your tests? Or should you hard code data? Or Should you combine both strategies? Etc).