TDD(a.k.a Test Driven Development) is one of the core methodologies of “Extreme Programming”, founded by Kent Beck. Extreme Programming (XP) has been successful as it puts more emphasis on Customer Satisfaction. XP encourages programmers to keep the design very simple and straightforward. XP significantly changes the way we code; it drifts from the traditional style of coding.
Test Driven Development is also known as “Test First”. TDD lays more stress on thorough unit testing. It's a usual practice to write and execute test cases after the coding is complete. The goal of TDD is to write clean code, but in TDD first we write test cases, then write the code and finally execute the test cases. That's the reason it's called “Test First”. It requires a different mind set from developers.
Traditional coding style
In traditional software practice we follow the below steps.
- Create the Technical Design Document.
- Write the Code.
- Create Unit Test Cases.
- Test the code based on Unit Test Cases
- Create the build and pass on to the test team.
Pitfalls of Existing Coding Style
- Most of the Bugs (which are of course nightmares for the developer community) are discovered during the test cycles, rather than at unit test phase.
- Identifying the root cause of bugs becomes very difficult.
- Code becomes tough to manage.
- We can never be sure that every line of our code is tested.
Implementing Test Driven Development
In TDD, we follow the steps below.
- Create the test case for testing each tiny bit of functionality.
- Run this test ( it will fail the first time as there is no code for this functionality.)
- Write only the code to pass the test cases.
- Run the test case again
- If the test case fails refractor the code to pass the test case
We repeat the steps again for the next piece of functionality.
TDD takes a different approach compared to traditional software development.
Here a test case for a specific piece of functionality is written rather than
code. The functional code is written only to pass that test cases.
Rules of TDD are
- Test comes first.
- Write functional code only if a test case fails.
- Make sure that your code passes testing 100% of the time.
Initially, adopting TDD can be pain for the developer community. The natural tendency of developers is to write the code first and the test next. Moreover they feel TDD involves too much of writing test cases rather than coding. Developers are not used to writing and executing large numbers of test cases.
To implement TDD these requirements are a must.
- A fast compiler.
- An automated tool for executing the test cases.
- Always use production data for your unit tests.
- In case if you don't have production data on time, spend some time to create test data similar to production data.
An automated tool is a must for TDD. Without which executing a unit test case will be very difficult and becomes more time consuming. I have listed available tools for different languages in the section below.
Benefits Test Driven Development
- The biggest benefit of TDD is verification. We can have an exhaustive set of automated unit test cases that can protect our system against defects.
- It is best suited to the systems where requirements are very dynamic.
- We can get a simple and clear design.
- Code becomes loosely coupled and much easier to manager.
- Test code provides a complete documentation.
- It ensures that the system is free from defects.
- QA time is saved as many defects and many of the bugs are worked out up front.
- The system we develop does what it needs to do and no more.
Available unit testing tools
Using TDD in Database Development
It has been three years since I moved into Database development using SQL Server, T-SQL and DTS. Implementing TDD here is a bit tough when compared to implementing it in C# and Java. The main problem is there are not good enough Unit Testing Tools for these languages at this moment. Although there are some tools like DBUnit, they are not widely accepted among the developer community.
What I did was write my own T-SQL programs and mock DTS packages for unit testing. The toughest job in unit testing database programs is creating the test data. If you are enhancing an existing system you can get production data, but if you are all together developing a new application then it's real pain to get test data.
I found a good tool for unit testing T-SQL called "tsqlunit". For more information on this you can find at
http://tsqlunit.sourceforge.net/ . I have been using tsqlunit for about 6 months , and it has proved very handy. I wrote a blog on "Unit Testing Stored procedures using T-SQL unit" you can find this at
TDD with example
I will explain how to implement TDD with an example.
Write a stored procedure "UpperText". This stored procedure
should take one input parameter and convert the input parameter to Upper Case.
Instead of writing the functionality from stored procedure
"UpperText" and then do the unit testing for it, in TDD we follow below steps.
Write Test case 01 to find if stored procedure UpperText exists in Database.
- Execute the Test Case 01
- The test case 01 fails as there is no stored procedure UpperText.
- Write code to just create stored procedure UpperText. (Point to be noted
here is , we code only to pass a particular test)
Execute the Test case 01, now it passes.
Write Test case 02, to verify if UpperText converts the given string to
- Execute the test case 02.
- The test case fails as there is no code written to convert the string to
- Write code to create a input parameter and convert input parameter to Upper Case.
- Execute the test case 02, now the test case passes.
My Experiences with TDD
My implementation of TDD is a bit different from XP. Below are the steps I used to follow
- Prepare technical specification once the functional specifications are ready. I would include very high level pseudo logic, data flow, class diagrams in the technical specification.
- After this I would list down the entire unit test features that I will be doing in a separate document.
- Create unit test cases for each feature.
- Start coding to satisfy the test cases.
- Test the code based on the unit test case.
- Log the results of each test case.
Though this process sounds very laborious at first glance, it really helps the productivity of the developers. Once we get used to the system it becomes very easy.
Best Practices for Unit Testing
- Test your code with realistic data (data similar to production data).
- Test your code with null values (something like pass null values to Form etc).
- Use automated unit test tools whenever possible.
- Try to use mock objects.
- Try to include more negative test cases.
- Examine how your code behaves under unexpected values.
Pitfalls of TDD
From my experience with TDD, the only pitfall is the developer community is not used to writing lots of test cases. Writing test cases for each and every piece of functionality and executing the code can be very tedious. I feel using automated unit testing tool like Nunit and DBunit really saves time in executing test cases.
TDD can give best results when implemented together with Pair Programming. Pair Programming is a concept of Extreme Programming. As the name suggests, in pair programming two developers work side by side on the same piece of work. They share the same workstation. One developer is the driver who takes care of the keyboard and the development activity while another developer, the Observer, carefully watches this code. So if the driver is about to make any mistake in writing code or a test case, the Observer can immediately report it. They also would often interchange their roles.