Channels ▼
RSS

Design

Scaling Test-Driven Development


Test-driven development (TDD) is a common agile software development technique. Although the name implies that TDD is a testing technique, it is actually a programming practice that has both specification and validation aspects. With TDD, you specify your software in detail on a just-in-time (JIT) basis via executable tests that are run in a regression manner to confirm that the system works to your current understanding of what your stakeholders require. Agile teams have been very successful applying TDD in practice, although a recent study has shown that teams are struggling to scale TDD to more complex situations. This is because TDD, by itself, doesn't scale—you need to apply other techniques to address the concerns that TDD doesn't cover.

TDD is the combination of test-first development (TFD) and refactoring. With TFD, you write a single test and then you write just enough software to fulfill that test. You can do TFD at the requirements level by writing a single customer test, the equivalent of a function test or acceptance test in the traditional world, and at the design level with developer tests. Refactoring is a technique where you make a small change to your existing code to improve its design without changing its semantics. Examples of refactorings include moving an operation up the inheritance hierarchy and renaming an operation in application source code; aligning fields and applying a consistent font on user interfaces; and renaming a column or splitting a table in a relational database. I have an overview of TDD at www.agiledata.org/essays/tdd.html and the Jolt Award winning book Test Driven Development: A Practical Guide (Prentice Hall, 2003) by Dave Astels is an even more detailed resource.

Figure 1 depicts the process of implementing a new feature via a test-driven approach. It starts when you pull a new feature off of your existing work stack to implement. You begin by formulating a customer test that specifies one aspect of the detailed requirements for that feature. For example, let's assume that you are implementing the functional to calculate the discount for an order and that you already have basic order-handling functionality in place. The first customer test that you would implement might explore what to do when a discount shouldn't be calculated; in this case the customer test would involve a customer who is not "elite" making a small order. To implement this functionality, you might first write a developer test that specified that the discount on an order with no items in it was zero and the supporting production code to do that calculation. Once that ran successfully, you'd add a test to verify that the discount for an order with a total of $999.99 is also zero, reflecting the business rule as it was described to you by your stakeholders. You'd then add a test validating that if the order is placed by a customer with a bad payment history, the discount is zero, and so on until you've got the "when not to give a discount" logic implemented. The next step in implementing the discounting functionality would be to write a customer test that specified what to do when a good customer places an order between $1000 and $5000 (give them a 1 percent discount) and sufficient developer tests to drive the implementation of the source code. You would proceed iteratively, writing sufficient customer tests and the supporting developer tests and production code to implement the complete feature. In parallel to this test-first programming, you would refactor any relevant production code that you find that wasn't the best design possible for what you were currently implementing. Once the feature is implemented, you'd pull another off the stack and begin again.

[Click image to view at full size]

Figure 1: Implementing a single feature via TDD.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video