0% found this document useful (0 votes)
49 views

When TDD Fails: September 24, 2011

Test Driven Development is the best way to write quality software. If you're not in love with it, you suck. Don't argue, just learn harder and eventually you will get it. Sounds familiar?

Uploaded by

Tomás Vásquez
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
49 views

When TDD Fails: September 24, 2011

Test Driven Development is the best way to write quality software. If you're not in love with it, you suck. Don't argue, just learn harder and eventually you will get it. Sounds familiar?

Uploaded by

Tomás Vásquez
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 3

September 24, 2011

When TDD Fails


Test Driven Development is the best way to write quality
software. If you're not in love with it, you suck. Don't argue,
just learn harder and eventually you will get it.
Sounds familiar? Unfortunately, it does to me. I've seen way
too many people with this attitude, both online and offline.
It's kind of ridiculous, considering TDD has obvious
problems in certain areas of programming. I haven't seen
many articles discussing these problems, so this is my
attempt of mending the issue. Partly, it's inspired by a
recent article on Peter Sergeant's blog.
TDD works well when most complexity in your code comes
from algorithms contained inside your methods or classes.
Let's say, you are tasked to write a function that calculates
the number of business days between two calendar dates.
Ideal for TDD. Fairly generic code with straightforward,
narrow interface and tricky logic inside. All you need for
testing it are two dates and a holiday calendar. It is easy to
come up with meaningful tests before you start
implementing anything. Moreover, this is the kind of code
that is likely to be reused and hence augmented with new
functionality in the future. The more generic it is
(dependency-inject the calendar!), the better.
TDD is nearly useless when your code is the opposite of
what I've described above: specific and mostly trivial, with
complexity coming from the sheer amount of methods and
their interactions. It's not that you can't test such code, it's
that your tests will not provide any value. Typical MVC
controller methods (actions) are a good example of this
issue.
Firstly, action methods often interface with multiple fairly
complex systems, some of which you don't have under your
control. Simply setting up a test requires you to add

numerous interfaces, wrappers, code for dependency


injection and so on. Now, many programmers would argue
that it's good design, but it really isnt if you use all that
added code just for tests and don't do anything with it in
your actual application. In that case it's pure bloat of the
same kind that plagues most enterprise software. Oh, and
good luck mocking your database and HTTP request
objects.
Secondly, action methods are not reusable. They express
specific logic applicable to a single scenario. You can, of
course, assert that your method PrintHelloWorld outputs
Hello world! before proceeding to write it. It might even
help you catch a typo by the virtue of you typing the same
thing twice. Problem is, that's about as useful as it gets.
Whereas testing generic logic allows you to assert some
fundamental properties of the system and the information it
works with (which will be used all over the place and are
unlikely to change), testing pieces of specific logic is an
exercise in proof-reading.
Not to say that such proof-reading is useless, it's just that
the kinds of errors it catches are pretty rare and can be
easily caught using much less labor-intensive methods.
Now, consider its downside: huge amounts of added inertia.
Business requirements changed? Rewrite your tests.
Someone changed names of the views? Rewrite you tests.
You want to use a different repository class? Rewrite your
mock code, and then rewrite your tests.
Thirdly, and most importantly, preemptive unit tests are
not going to catch the bugs that arelikely to happen within
and around your action methods. They are not going to tell
you about a typo in the field name of an HTML form. Neither
will they pinpoint a missing record in the database. In other
words, they are not going to catch the bugs that arise on
the boundaries of different subsystems in you app.

I was speaking about action methods, because they are a


good illustration, but, of course, there are lots and lots of
similar types of code out there. Glue code. Simple methods
that interface with several complex subsystems.
That code is wrong. Anything that is not testable is bad
design. Anything that is designed using test-first
methodology is good design.
Okay, maybe I'm going a bit overboard with fake quotes.
Still, it is also a real, popular attitude I see among
developers. They are equating a particular development
process with quality, even though that process is used to
ensure quality. It's a kind of circular argument.
Sure, unit testable code is not going to be a horrendous
spaghetti of giant methods that do twenty different things
each, tweaking global state every step of the way. But there
are plenty of other ways to develop crappy software. Create
countless layers of abstraction. Make everything a
framework, pushing all the real work (and bugs) into
configuration files and the database. Split functionality into
tiny pieces that make no sense on their own, but somehow
work together. I've seen it done. Heck, going overboard with
test-fist approach sometimes encourages these things.
My point? I guess it's similar to the one made by Peter
Sergeant. I'm not saying TDD is a bad thing, but there are
more tests than unit tests, and there are more ways to
verify software than testing. If you choose a methodology
without comparing it against alternatives, if you claim that
it works all the time without evaluating the results, than
you're not doing engineering - you're practicing a religion.

You might also like