Contractual Test-Driven Development (DBC with TDD)
This article is written by Dave
Chaplin, an IT Consultant with 10 years experience. He leads and mentors teams of developers
on agile .NET projects and has extensive experience in agile development techniques, particularly
Test-Driven Development. Dave can be emailed at
Tuesday, April 22, 2003
Test Driven Development (TDD)
is at the heart of Extreme Programming and is used to add significant quality
to the programming process. It drives the development and ensures you only
build what is required for a particular test case, rather than spending time
developing the system for what ‘might be’ needed in the future. Productivity is
enhanced since the system is continuously regression tested. Better design is
achieved since writing the tests first helps to validate existing design
decisions and refine and improve them.
Design By Contract (DBC) was invented by Bertrand Meyer. It adds a significant
quality aspect to the design and programming process. The technique enormously
improves development productivity by ensuring that what is built conforms to
the defined specification. It provides clients with a precise definition of the
behaviour of a component. Integrating components becomes much less painful and
code bloat is reduced by removing the amount of error checking code required.
The two techniques do have some overlap and also some areas of confliction.
This article discusses effective ways to blend the two techniques to further
increase quality, and thus productivity, in an agile development process.
Account Deposit with TDD
Below is an overview of the techniques.
In TDD we write a test before we actually write the code. The test sets up an
initial condition (like creating an instance of something). We then run some
code against it, and then assert that certain conditions are true. It works
Step 1: Write the test:
Set up an initial condition and write some test code against it with some
Lets say I want to write an account object and then be able to deposit money
into my account. Yep, our good ole friend the account object has popped up
again. My test code, written using NUnit 2.0 would look something like this:
Note that, in order to be able to test the Deposit method on the Account object
I needed to have a Balance property. Thus, TDD has driven out a design
decision. I still haven’t written the account object yet, which is why I have
the blue wiggly lines indicating it will not compile.
Step 2: Get the test to compile:
To get things compiling I create an account class that does nothing, but
adheres to the interface defined in the test:
[I have also added the ‘using Domain;’ line to the test class to get it to
So, now when we run the test in NUnit we get a red light because the assertion
Step 3: Code until the test passes:
All we do now is complete the code until the test passes:
Now, when we run the test we get a green light and we know we have completed
Granted, there are some gaps in the code at this point: what happens if I try
to deposit a negative amount? Well, lets say that if we try to deposit a
negative amount then an exception should be thrown. [We shouldn’t really be
throwing expections for business rule failures which are not exceptional
circumstances, but it will help illustrate some ideas.]. The test looks like
I’ve thrown an application expection here, but you could define expections that
are more meaningful. This test fails, so we now write the code to pass the
The tests now pass. There are also some additional questions you could ask. For
example, can I have an overdraft? Well, if we think in terms of TDD, the only
requirement we have at the moment is to deposit an amount, and we have achieved
that, so we move on. That is the essence of TDD with XP. Build only what you
need now. If we need to enhance things later then we will do so. We will also
refactor to change the design when required, with the comfort of a suite of
tests that tell us if we have broken anything.
Lets now look at how things would turn out using DBC.
Account Deposit with DBC
DBC is all about 3 things:
preconditions : things that must be true before we invoke a method.
postconditions : things that must be true after a method is invoked.
Invariants: things that must be true both before and after a method is invoked.
For our account object withdraw method we could state the following DBC rules:
Pre : depositAmount > 0
Post : Account.Balance = Account.Balance@pre + depositAmount
Inv : Balance > 0
For the sake of this example, I’ve just invented a requirement here that says
you have no overdraft facility. This then means I have an invariant which
states that the balance must always be positive.
Note also the use of the ‘@pre’ symbol. This means the value of the property
before the body of the method call was invoked.
Now, lets see what this looks like in code:
C#.Net does not have DBC support built in so I’ve had to write ‘@pre’ values to
local variables at the start of the method body that can be used later in the
method. This is a pain.
The DBC class has a bunch of methods that simply check the assertion passed and
throw an exception with the passed message if the assertion fails. You might
want to define different DBC exception types if you wish to distinguish between
the varying types.
I’ve not written any code to roll back the transaction if the post or invariant
checks failed. This is not required, since the DBC checks are compiled out for
the release version. In DBC the client (calling code of this method) is
responsible for ensuring that it adheres to the precondition before it calls
the method. If the client illegally calls the supplier, then the supplier makes
no promises about what will happen. The behaviour is essentially undefined.
This removes the need to put lots of exception catching code in the client. If
you wish to leave the DBC checks in at run time you can, but if one fails there
is no much you can do about anyway. The system has a fault, and needs to be
Comparison of TDD and DBC
Both sets of code using TDD and DBC pass the tests.
During TDD we design for the specific (what we are building now) whereas in DBC
we think more generally about the object itself regardless of who uses it. The
focus is wider. The two methods conflict. With TDD we have a very narrow focus,
which enables us to quickly build what is required now, whereas with DBC we
have a danger to wander off into the ‘what if’ cases.
If the methods require precondition checks then TDD requires you to write a
test for each condition which can result in an exponential explosion of tests
when the number of preconditions increases. You also need tests for the edge
cases. With DBC you don’t get that explosion at all since the precondition
deals with the general case. The same argument can be used for invariant
Because you are continuously testing TDD builds extra quality into the
programming process by ensuring that breaks in the code do not occur as changes
are introduced. DBC does not give you that comfort, although you may well have
an automated test harness you can run. With TDD, the harness pops out as part
of the process.
Using DBC precondition checks and the DBC method means that client code does
not have to check for exceptions thrown due to preconditions failing. With the
way I’ve used TDD it means the client code has to be aware of the exceptions
that can be raised. Granted, this is a weak argument, since you could turn off
the precondition checks in TDD for production code.
Both TDD and DBC force design decisions to ensure client code can check a
methods preconditions before it is called. This is good design, which ensures
that the calling code can change it’s behaviour if the supplier is not going to
pass the preconditions. For example, rather than trying to withdraw a negative
amount the user could be redirected to an area of the application that offers
the ability to apply for a loan. This is more powerful than trying to capture
an exception then change the behaviour based on that exception. Although the
last statement is more to do with using exceptions for the right purpose than
TDD and DBC driving the proper use of exceptions.
So, given the above arguments, and my experience of using the two techniques
together I believe the techniques I describe below effectively combine TDD and
DBC into what I loosely call Contractual Test Driven Development (CTDD).
Contractual Test Driven Development (CTDD)
The follow points below are guidelines for doing contractual test driven
Do not write tests for negative behaviour. Use a DBC precondition check instead
which can be compiled out at run time.
Use post condition checks if you want, but don’t re-write the whole body of
code. [ if you work with a DBC supported language, like Eiffel.Net, I would
suggest using full DBC and derive generalised post conditions from your TDD
assertions. This is just an idea though, I’ve not actually tried it in
practice. It could reduce the amount of test code.]
Use Post conditions where you can without re writing the whole body, or have to
then introduce a lot of code because your language does not support DBC.
Turn off DBC checks for production if performance is an issue.
Leave DBC checks in the code if the system is life critical.
Benefits of CTDD
The benefits from TDD are:
The benefits from DBC are
building only what is required now. Keep it simple and well focused.
a suite of automated tests for effective refactoring, continuous integration
and regression testing.
Design decisions are driven from the tests.
the code quality is higher due to the precondition checks.
you do not need all the checking code in the production code which forces code
design decisions are driven from the preconditions.
cleaner code since there is no need for checking code in the method body.
CTDD In Practice
The CTDD technique was developed in practice, rather than theory, by an XP team
that I am currently leading. We started with some “interesting ideas” about how
it could be done, some of which were clearly flawed when it came to actually
trying them out. The methods I describe herein are now practiced by the team
wholeheartedly and we have found that adding DBC to the TDD equation has
significantly increased the quality of the code, particularly the refactoring
and debugging activities.
A sincere acknowledgement goes to Duncan Green, who helped develop and practice
these ideas during the agile development at Freshfields Bruckhaus Deringer.
Duncan is a superb technician and designer, and pragmatist who has a shared
interest good design and high quality.
Closing Comments (A Dose of Reality)
Whilst I’ve coined the phrase CTDD here, I’m certainly not going to try and
pretend that I’ve invented something new, by any stretch of the imagination.
TDD, DBC and the use of assertions were invented years ago. What I’ve described
in this article are observations of how, in practice, I’ve personally managed
to combine the techniques.
Happy developing (not debugging!).
Test Driven Development (Dec 2003)
The Losers Olympics (Sep 2003)
Making Projects Succeed: Part 1 - Measurable
Business Goals (Sep 2003)
Pitfalls In Software Development (June 2003)
Extreme Web Architectures - Testing Web Applications In
Seconds (June 2003)
Pair Programming and Quad Programming - From
Experience (June 2003)
Making Extreme Programming A Success (April 2003)
Contractual Test Driven Development (TDD with DBC)
Moving To XP (Feb 2003)
Maximising Development Productivity (Dec 2002)
Writing Automated Browser Tests Using
NUnit and IE (Oct 2002)
Mitigating Requirements Risk With Agile
Practices (Oct 2002)
10 Tips for Successful Team Leading (Oct
Developing Automated Using Tests Using NUnit 2.0
With VB.NET (Sep 2002)
Quality By Design - Part 1.doc (May 2001)
Quality By Design - Part 2.doc (May 2001)
Quality By Design - Part 3.doc (May 2001)