Channels ▼

Andrew Binstock

Dr. Dobb's Bloggers

Acceptance Test Driven Development

February 16, 2011

In response to my editorial anent TDD as a design practice rather than a validation process, I received several thoughtful comments. These discussed the fact that while TDD can make you think about your code, unit tests in themselves are insufficient to test code. I agree wholeheartedly with this perspective — and I should note that most professionals who use TDD would also agree.

Unit tests must be combined with higher-level tests, before developers can begin to feel that their code is reliable and conforms with the user’s stated needs. Because of their low level of granularity, unit tests can fulfill neither one of these mandates. In one letter to me, Capers Jones, noted that in studies, unit tests remove only about 35% of defects in software. This number rises to 40% if the tests are written before the code.

The stand-out question then is: Are unit tests the right level of test for doing TDD successfully? I have long maintained that they are not. My preference has been higher level tests. For a long time, I thought integration tests were that better level. But as time has passed, my experience has led me to move up the chain even further. I am becoming convinced that the right level to work at before writing code is the acceptance test.

Acceptance tests have several key advantages over lower-level tests:

  • As a design framework prior to coding, they focus the developer on the user's needs. This is an important benefit. It is much easier to design functions correctly, when you can see them holistically, rather than the bottoms-up approach of TDD where the focus is on tiny steps developed within the scope of a single function.
  • The developer validates the code at the level of the user experience. If the previous benefit was important, this one is crucial. It is entirely possible to write software that enjoys 100% code coverage, where every unit tests passes, but whose functionality is still broken. Even if the functionality is correct, the software still might not do what the user requested. In counterpoint, if the code is defined by acceptance tests, it is no longer possible to pass all the test and not work or not do what the user requested. Passing all acceptance tests (presuming they’re correctly written) guarantees satisfaction with user needs and validates the software.
  • Acceptance tests document the software. This last point gets at what is one of the most pervasive misconceptions about unit tests: that they document the code. This is a canard that keeps being tossed about as a good reason for writing unit tests. It is, in a word, nonsense. If you’re looking at unit tests as documentation for the code, something upstream is seriously broken. (Allow me to take this up in a separate column, so as not to get too far off topic here.)

The use of acceptance tests to drive TDD is a point of view that has gained traction in various parts of the industry over the last decade. Its most established home is in behavior-driven development (BDD), which works by transforming use cases and user requirements into an extensive set of tests that the  code must subsequently satisfy. There are many BDD tools in the OSS bazaar. One of my favorites is easyb, which won a Jolt award in 2009.

Lately, the term acceptance test-driven development (ATDD) has emerged in its own right and stresses the use of acceptance testing tools, such as Fitnesse, to steer coding. How these tools can drive development is thoughtfully explained in a recent book by Ken Pugh, which I recommend if this approach makes sense to you.

What ATDD does is substitute a higher level of tests in the TDD process. It's important to note that it does not denigrate the use of unit tests. It simply forces the developer to think at a higher level and focus on the user’s needs all through the implementation.

Andrew Binstock
[email protected]

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.