TDD, Unit Testing and Benefits

What is TDD?

From Wikipedia, quoting,

Test-driven development (TDD) is a software development processthat relies on the repetition of a very short development cycle: first the developer writes a failing automated test case that defines a desired improvement or new function, then produces code to pass that test and finallyrefactors the new code to acceptable standards. Kent Beck, who is credited with having developed or ‘rediscovered’ the technique, stated in 2003 that TDD encourages simple designs and inspires confidence.[1]

Test-driven development is related to the test-first programming concepts of extreme programming, begun in 1999,[2] but more recently has created more general interest in its own right.[3]

Programmers also apply the concept to improving and debugging legacy code developed with older techniques.

TDD Cycle

TDD Cycle

 

Although TDD doesn’t mean you write your tests first, test-first development relies on the process of writing a requirement to add a feature, functionality in the form of short unit-test, watching it fail first, then implementing the classes, methods and properties defined in the test, bit-by-bit, and then watching it pass, which is why it’s also sometimes termed as red-green (fail-then-pass) refactoring. Test-first or not, Test Driven Development makes Tests first class citizens of development process, rather than an after-thought.

 

Concerns and Benefits

There have been several cases against using TDD or Unit Tests in general, common concerns being,

  1. Oh, this means the developers have to spend extra time writing unit tests, which they could be spending on “actual” development adding “features”.
  2. Well, it’s going to either need more developers to make up for the time lost and increase project costs.
  3. So you are saying we don’t need QA anymore, if Unit Tests are going to take care of all the testing?
  4. and so forth…

Some benefits of Unit Testing in general,

  1. The Project is going to gain a lot more time actually spent on quality, although more time might be required upfront to ensure unit tests are written for as many cases possible. However, the confidence in the quality of the code will be high for each developer. They will be able to know a defect they fixed is not going to break something else, very quickly. Immediate feedback, less QA cycles.
  2. Cost associated with adding more developers is going to pay back once you have lesser QA cycles, immediate feedback on buggy code, lower long term maintenance and QA costs. It’s important not to conclude based just on the initial increase in development time and cost.
  3. Generally it’s not a good idea to add more developers just to write unit tests for code that’s being written by some other developer. Ideally each developer who implements a feature or functionality has to write his/her own unit tests, and then be peer reviewed for accuracy and design
  4. Unit tested and TDD code is likely to create and force automatic optimum design, also it’s going to help discover bugs in existing/legacy code – this is why it’s also sometimes called Design Driven Development. The API is going to evolve and emerge just enough to end up being optimum, on-demand design and avoid any upfront, grand ivory tower design that usually is a pattern in the Waterfall methodology.
  5. Unit tested code is more likely to create a sense of ‘care for the code’ from a developer’s standpoint, and not writing code ‘just to make things work’
  6. There could be more many more that I missed, please feel free to add.

Now, these benefits depend on how TDD is adopted and practiced and the results may vary on case by case basis. Also there are situations when writing unit tests for every part of the application is not feasible or possible. For example, UI testing, which is a whole another topic. For UI testing it is recommended to have Automated Coded UI tests, validating parts of the application that can not possibly be tested using Unit Tests.

Types of Testing

Generally there are 3 types of Testing areas. It’s important to know their differences and purpose.

  1. Unit Tests – focus on testing classes, methods and API in general, interacting with APIs of the various modules of the application. Goal is test functionality at a micro level and make sure each unit of code is accurately functioning as expected.
  2. Integration Tests – focus on testing multiple coherent components/modules of the application. Goal is to validate if they work together as expected. This might include Presentation layer interacting with Business logic / Middleware and databases.
  3. Automated/Coded UI Tests – focus on UI and how the user interacts with the application – test cases generally not covered by the Unit Tests or Integration Tests.

All the above 3 types of tests are known to significantly reduce cost, maintainance and resources for the Project.

Research and Case Study

To that point, a research was conducted by folks at Microsoft which weigh in costs development time vs benefits.

Quoting from that research whitepaper,

Test driven development has recently re-emerged as a critical enabling practice of agile software development methodologies. However, little empirical evidence supports or refutes the utility of this practice in an industrial context. Case studies were conducted with three development teams at Microsoft and one at IBM that have adopted TDD. The results of the case studies indicate that the pre-release defect density of the four products decreased between 40% and 90% relative to similar projects that did not use the TDD practice. Subjectively, the teams experienced a 15–35% increase in initial development time after adopting TDD.

Link to the WhitePaper (thanks to @jslicer for the discovery of this whitepaper)

Great article on several terminologies related to Test practices (Test first, BDD, TDD, Executable Specs etc)

 

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>