TrainingConferencesAbout UsContact UsAdvertiseSQE.comRSS Feed

StickyMinds.com: brain food for building better software

Log In
 Clarify Your Search Criteria

Tips on Using Our Search Feature(s)
 
StickyMinds.com Home
ResourcesTopicsCommunityPowerPassBlogs
Home  >  Detail: Test-Driven Development Isn’t Testing


A StickyMinds.com Original
Article Picture
Test-Driven Development Isn’t Testing

By Jeff Patton

Send This Content to a FriendGet a Short Link to This ContentPrint This ContentSee User Comments About This Content

Summary: There's a common misconception that test-driven development is a testing technique when in fact it's a design technique. In this week's column, Jeff Patton explains this and how you might use your unit tests to explicitly guide and describe the design of your software.


Rally Software
For those already doing test-driven development, you probably know that test-driven development is not testing. So, go ahead and grab a cup of coffee, but you should keep reading to see if you agree or disagree. 
 
For a few years I've been using unit testing frameworks and test-driven development and encouraging others to do the same. The common predictable objections are "Writing unit tests takes too much time," or "How could I write tests first if I don’t know what it does yet?" And then there's the popular excuse: "Unit tests won't catch all the bugs." The sad misconception is that test-driven development is testing, which is understandable given the unfortunate name of the technique. 
 
Test driven development is actually a design technique.  
 
If I were designing a bit of code the old-fashioned way, I'd think about the object I was about to create, what it would do, and maybe even write it down or draw a UML diagram. Then I'd write the code. But now I'd start by writing a unit test in my favorite unit-testing framework. (Here's where I get to have fun and pretend I've already written the code for my object.) So, while still imagining my object, I'd ask, "What would its class name be? What other objects would it collaborate with? What methods would I call on it? What would they return?" In my unit test, I instantiate the imaginary object and ask it to do a bit of work for me, which I would assert it did flawlessly. Afterwards, I'm left with a little bit of code that uses the object I have to build, and describes exactly how the object will be used. I've designed the object -- now I just need to write it. 
 
If you're a java developer using a newer IDE, then you know the tests you write give your IDE the information it needs to write much of the code for you. For example, the IDE might offer to create the class and any methods you'd used in the test case, saving you lots of typing. After creating the class, I implement the methods I've described. Here is where it gets fun: I know I've implemented the code as designed by running the unit test!  
 
Once you start looking at your test cases as a description of the software design, they start to look different. Pay attention to the names of your tests. Instead of writing tests named after a method on an object you're testing, try using the test name to capture the intended consequences.  
 
Instead of a single test for the processFoo() method on your object:  
testProcessFoo()  
 
Consider: 
• testProccesingFooProducesBar() 
• testProcessingFooLogsTimingsToFooLog() 
• testProcessFooWithBadinputThrowsExceptionContainingBadData() 
 
If I convert those test names to sentences, I might end up with something like this: 
• Processing a Foo produces a Bar. 
• Processing a Foo logs timings to the Foo Log. 
• Processing a Foo with bad input throws an Exception containing the bad data. 
 
Now my names look more like design specifications! Folks who've been doing test-driven development for years see it this way. In Alistair Cockburn's book Crystal Clear, he specifically points out the importance of readability of the test case as a design document. Nifty open source tools like TestDox from Chris Stevenson actually let you browse and write test cases in your IDE as little bulleted design documents.  
 
Now that we've established that test cases can describe design, let's talk about how they can morph into tests.  
 
Following the rhythm described above:  
• Describe design in the unit test.  
• Write the code to make it work. 
• Validate that it works by running the test. 
 
If we repeat this enough times we'll have a lot of these little tests that describe the design. In Hunt & Thomas's book Pragmatic Unit Testing, they suggest asking some questions at this point:  
• What else can go wrong?  
• Could this same kind of problem happen anywhere else? 
 
The answers to these kind of questions detail my design around edge cases that could cause problems. Thus I start to explicitly deal with designing for and validating the design of the code in a variety of tough conditions. Now this starts to feel more like testing. 
 
At the end of the day, my fattened test case includes all the tests I wrote while I was imagining the design of my conceived of object, and all the tests I wrote while trying to put my newborn object through a workout. There's at least as much code in the test case as in the actual class being tested.  
 
I guess this makes it sort of "design and test," but in the end we still haven't ensured our object is bug-free. We just know where the bugs aren't-–and where the design is. Unit tests have been compared with shining a flashlight into a dark room in search of a monster. Shine the light into the room and then into all the scary corners. It doesn't mean the room is monster free-–just that the monster isn't standing where you've shined your flashlight. 
 
Looking back at the three common reasons for not writing unit tests, let's substitute design for test: 
• Designing takes too much time.  
• How could I design first if I don't know what it does yet?  
• Designing won't catch all the bugs 
 
Those statements sound a bit different now don't they? For those making these sorts of statements about unit testing, be aware that those proficient in test-driven development might be rolling their eyes because the above design statements are what they hear. For those already doing test driven development, put down that coffee and go help others understand your cool design technique. 
 
Sources on the Web: 
TestDox from Chris Stevenson
 
Pragmatic Unit Testing
 
Alistair Cockburn's Crystal Clear 
 
Editor's Note: For more on this topic, look to the February issue of Better Software magazine, featuring "Double Duty: Using the Unit Tests You're Doing to Help with the Documentation You're Not," by Brian Button. Brian will also facilitate a StickyMinds RoundTable discussion on the topic from Feb 7 - Mar 18, 2005.


About the Author
Jeff Patton is a developer, and user centered designer. He's developed on and coached teams of Agile developers for the last several years. A regular contributor to Better Software magazine and StickyMinds.com, he proudly works for ThoughtWorks.

Back to Top
 
 

Member Comments
Add Your CommentExpand Comments
 
Comment:    
by Steve Webb 5/11/2008

Jeff, thanks for the great article on TDD. I’ve just completed a successful financial application using XP. About half way through the project I found your article about naming tests and suggested to the team that we should adopt this approach, it proved to be a popular suggestion. One of the benefits is that it made it easier to explain to new members of the team the intention of the code.

Agility Thoughts


 
 
Comment:    
by Tom Pimienta 8/29/2007

"Shine the light into the room and then into all the scary corners. It doesn't mean the room is monster free-–just that the monster isn't standing where you've shined your flashlight."

What if you make the room small enough that there isn't anywhere left for the monster to hide?

Author's Response:
8/29/2007    
The room might not be big enough to live in/be interesting. And, the monster has a clever way of hiding in the hallway between rooms. ;-)

Seriously though - the metaphor breaks down fairly quickly. Even using code coverage tools to make sure every line of code is tested, I've still observed problems with the code. Often times those problems trace back to boundary conditions in values, problems with the way one bit of code interacts with another - the stuff you'd catch with acceptance tests, or problems where intended or desired use results in unexpected and untested input. I supposed these might be considered requirements problems - or as a friend of mine used to say to analysts who handed off bad requirements: "there's a hole in your side of the boat" - meaning ultimately it doesn't matter who's fault it is, software quality is still what what's expected or hoped for.

I'm sure there's a way to write unit tests that really "shine a light into every corner of the room." In practice, I haven't observed it.

 
 
Comment:    
by Robert Kohlenberger 3/23/2005

The author is right, tdd is a design technique. Explicitly, it is a technique to design *to* the test. The consequences are similar to a classroom technique called "teaching to the test". The only material students learn is what educators thought to put on the test. The same is true with tdd; whatever is left out of the test will be missing from the design also. I like the comparison of unit tests with "shining a flashlight into a dark room in search of a monster. Shine the light into the room and then into all the scary corners." But it points up a possible weakness in tdd. We can get carried away writing tests...Read On

 
 
Comment:    
by Mike Whittaker 3/8/2005

"Nifty open source tools like TestDox from Chris Stevenson actually let you browse and write test cases in your IDE as little bulleted design documents" According to the website quoted, this tool just converts unit test function names into phrases - not quite what you said (although that would be nice ...) The article is still a very useful overview.

 
 
Comment:    
by Suresh Marur 2/22/2005

I need to know if unit tests have been used in systems/products where the execution environment is complex (with databases, directory servers, network protocols etc.). For most applications, testing without these environment amounts to little other than testing base libraries which are generally stable. Most examples for unit testing I have come across seem to be at a very low level with very little insight on how to build test suites that work in complex environments. Using mocks and such techniques are nice but testing in isolation is not production, so we end up doing manual integration tests anyway. This to me adds to the cost of...Read On

 
 
Comment:    
by Kay Johansen 1/28/2005

Jeff, great article. When I was a developer - before I joined the "dark side" - if I thought about testing at all I just lumped the concept "testing" into a few, scarcely thought through categories: unit testing, integration testing, load testing, and, well, the rest. As I become more involved in testing, I'm thinking there are as many different kinds of "testing" - with different purposes - as there are kinds of "snow" to an Eskimo. I delight in the diversity of the field, but it does lead to serious communication problems like the one you describe. Your article is a big help - I'm going to use it...Read On

 
 
Comment:    
by Geoffrey Slinker 1/28/2005

Great article. I have recently started doing test driven development as an individual. The company has not adopted this approach yet but I feel momentum going that way. I have always been one to talk about interfaces, how things will be used, etc. I have used diagrams and such to share the ideas of what the iterfaces should be before the team goes to work. I am new at this and may still be doing some things "wrong" but I find that test driven development is designing and it flushes out the "usage" of the objects and the terms that describe the domain! These two things are often some of the biggest stumbling blocks...Read On

 
 
Comment:    
by Andrew Lawrence 1/26/2005

I'd certainly agree with the article. Test Driven development is much more of a design activity than a real testing activity. The article points it out well. And hopefully it will cause some doubters to try it out. However I also think it is good to point out the regression aspect of unit tests. Many people agree that unit tests are great for regression testing -- the problem is that they don't want to take the time to write them. Doing test-driven development causes those tests to be written. So while it is "design work" it is also design work that sticks around and makes sure things are always operating correctly. ...Read On

 
 
Comment:    
by Bret Pettichord 1/26/2005

I like the way you emphasize that TDD is "design AND test." It's not independent testing (or a complete substitute for it), but it also isn't not-testing. You say "in the end we still haven't ensured our object is bug-free. We just know where the bugs aren't." But of course, this is true of any kind of testing. The first law of testing is that testing can never prove the absense of defects, only their presense.

 
 
Comment:    
by John Daughety 1/25/2005

I have been pushing automated testing, mostly to people who have told me to make it as absolutely simple as possible, because it is only extra work for the developer and if it adds too much time to their process it won't get done. My answer to this concern has always been "just use the time you normally spend in design." In my mind, at the very least it is a way to get developers to think a bit more before coding, a situation which almost always leads to less buggy code. When breaking down the total cost of quality, I would put the cost of this work into the Prevention bucket, since as other commenters have said its benefit is...Read On

Author's Response:
1/25/2005    
In this short column I am guilty of understating the huge benefits of a codebase supported by comprehensive unit tests. I've never had much luck telling people how much more confident they'll feel about their code, how much more relaxed they'll be about making major changes to it, and finding and fixing bugs. I can say it, but they don't seem to get it until they feel it for themselves. So like you're suggesting I try to make it look and feel simple - to make it feel like the design they're already doing. They'll get the big benefits for free and become test infected soon enough: http://c2.com/cgi/wiki?TestInfected If you're looking for open source tools that will improve the quality of and your confidence in your codebase I'd highly recommend using CruiseControl [http://cruisecontrol.sourceforge.net/] to automate your build. Make sure your continuous build runs unit tests. Then incorporate test coverage tools like emma [http://emma.sourceforge.net/] or clover [http://www.cenqua.com/clover/]. Then top it off with some simple code metrics like javancss: [http://www.kclee.de/clemens/java/javancss/]. These tools produce easy to read html output about your codebase. You'll be surprised at how quickly developers respond to fill in tests when they see they forgot to test just a couple lines of a method [emma shows this]. A very smart friend of mine draws one of those overused four quadrant graphs with cyclomatic complexity [http://www.sei.cmu.edu/str/descriptions/cyclomatic_body.html] -CCN from javancss- on one axis and code coverage percent on the other. He suggests focusing on the high risk quadrant - the one with high CCN and low test coverage. That's the place in your code where you'll have the highest risk - and likely the most bugs. Thanks all for your comments.

 
 
Comment:    
by Erik Petersen 1/24/2005

Jeff, I have been saying similar things at conferences recently. It is design driven development during build. At maintenance time, providing the correct tests were created at build, it is now test driven development as changes to the code with unexpected side effects cause test failures that then need code correction. The other major aspect is the fact that tests need to be created in advance forces a simplicity on the design to allow it to be testable. I have seen some incredibly complicated programs that were almost unmaintainable in the past; These would never have been created using design/test driven development. I've also heard...Read On

 
 
Comment:    
by Frits Bos 1/24/2005

Jeff, an interesting article, even though I think you may be a bit tongue-in-cheek in terms of what is accomplished by this testing. On the surface, one can only agree that test driven development and testing are not the same: it would be a stretch to consider it equivalent. However, if you dig a bit deeper, when the focus is to get a product that reliably delivers what is expected of it, then the test driven development and testing activities are perfectly complementary. To the comment that test driven development is not investigatory, of course it is not if you can prevent bugs from being introduced in the first place. You cannot...Read On

 
 
Comment:    
by Michael Bolton 1/24/2005

Interesting coincidence--this is just what I've been saying on the Agile Testing mailing list just lately, but from the tester's perspective, rather than the programmer's perspective. As a tester, I lean very strongly towards the investigative side of testing. TDD and programmer tests are wonderful things, but I would contend that they're not investigatory; they're confirmatory. To paraphrase the article (and von Clausewitz!), they're specification by other means. To me, that distinction is at the heart of the difference between the role of the developer vs. the role of the independent tester on the same team. It is the perspective...Read On

 
Back to Top



 
Ads By Google
What's This?
 
 



Home   |   Resources   |   Topics   |   Community   |   PowerPass



© 2010 StickyMinds.com. All rights reserved.
StickyMinds.com is a division of Software Quality Engineering.
Privacy Policy    Terms & Conditions    Link to StickyMinds.com    Feedback


Klocwork

Infosys




STARWEST 

Agile Development Practices