Test Driven Development (Part 1)

Over at AgileDeveloper.com they are running a three part series written by Venkat Subramaniam on Test Driven Development, or TDD for short. The series is going to be divided as follows:

  • Part I: using NUnit to write out your test cases
  • Part II: Mock Objects
  • Part III: Continuos Integration

The rational of writing test cases first according to Venkat are as follows:

“In Test First Coding, as we write the test code before writing the class, we are motivated to think about how our class will be used. Without it we focus more on implementation. This approach, on the other hand, let’s us focus on how our class will be used. This leads to a design that is simpler and pragmatic. We can start out with a general understanding of the design with a high level UML diagram. However, once we get into developing the code, the unit tests can pretty much drive our design.”

The series teaches you TDD through example. The author uses as an example a Tick-Tac-Toe game and takes you through the whole process of creating the test cases for the game.

The tutorial is written in C# but I don’t think it will matter if you are or are not familiar with the language as long as you are familiar with OOP (object-oriented paradigm).

Only Part I is presently available. As the next pars become available I will post them here as well.

Do you do TDD? What are you impressions of it? Would you ever go back to writing the code before the tests?

written by: John Kopanas

Related Links:


Help Support Us By Visiting Our Sponsor

10% of our revenue from these ads go towards scholarships!


Comments

October 12, 2004 03:05 PM | mcs commented:

Only danger with writing the tests before the code, is if you start to think in terms of the test cases (and you do not have a complete set of test cases).

If you have a complete set of test cases your find— but if not, your coding/designing a series of patch work solutions. Example: Think back to early in your academic careers: You write a program to caculate the cost of something given a sales tax(as input). The test cases you come up with are a series of dollar values and percents. You believe that this is complete. And you have satisfied all of your test cases.

After your done, someone asks what happens if you say the sales tax is 0%- do you get an answer of $0 (00.00%) or do you get an answer of $x ($x1.00%)?

If you didn’t think of this when you started, you might be tempted to go in and throw a quick if statement in the code to solve this. Next someone else points out that prices are never displayed to the thousandth of a cent ($0.000). So you quickly throw another patch work solution on. The program is not quickly getting messy because you did not think of ALL the test cases.

Conclusion: Testing and Design/Coding should be done by seperate people.

October 15, 2004 12:47 PM | David Di Giacomo commented:

I love the idea of fixing a bug and then knowing for sure, through TDD, that it won’t break later because you have a test case running on every compile that will tell you.

During the acceptance test for the last project I delivered, I could easy say that a minimum of 40% of the bugs we fixed were a result of some previous working code that broke after we fixed a previous bug.

In my opinion though, its not easy to implement. First, you have to know how to write appropriate test cases. When I first started reading about TDD, I looked at the classes I was in the process of writing and I wasn’t exactly sure what the appropriate test cases would be.

2nd, every class needs a seperate test class (if you’re using JUnit)… so developers must accomodate for this and structure their application appropriate.

Then, its about changing mentality… any effort spent by programmers not writing code is usually thought of as wasteful… thats why design tends to always fall a little short, thats why test cases are not written properly - people like jumping into the code…

So, I’d like to get to a state where we are using Ant and JUnit to ensure our applications are correct as they can be, but I think the road ahead will be long and arduous.

October 22, 2004 01:11 PM | John Kopanas commented:

The whole idea behind creating unit tests before you program is to help you better understand what your function is going to do in the first place. By taking the time to write your unit test you will be able to better understand your function and be able to conceptualize it better.

I would prefer ugly test cases then ugly application code any day of the week. Unit tests I think would be simpler to implement then the function itself in most cases as well.

October 22, 2004 06:43 PM | Ness commented:

The minimum number of test cases for each bug found in a product would have to be >= 1. Would anyone like to disagree with that?

So look at a product like Gnome Desktop which is a large collection of programs. I pulled up bugzilla and found a recent bug (~18:00 today) was number 156,180. Not sure if that number rolls over or whatnot with time.

But as you can see, writing atleast_ that many test cases could be painful. And complex bugs could generate many more than the trivial single test case.

I’m pretty sure it’s Brooks who said: “Testing can find problems, but it cannot verify the absence of problems.”

October 22, 2004 07:04 PM | John Kopanas commented:

I know someone did say that and that person is absolutely right. But you used the quote out of context. There is a difference between failure and fault and there is such a thing as doing quality assurance which has nothing to do with if the application runs without failure or not. I don’t disagree with the quote at all and I am sure everyone hear would also agree.

The numbers unfortunately don’t tell the whole story. The only numbers that are important are financial and lives. One bug can be the difference between project failure and success. Living and dying. So why take the chance with making a change and then just praying that it works?

For me it also had to do with morale. I liked to develop software. Fixing is another thing. If I spend more time chasing bugs from a bug report that I could of caught right away with a test then innovating I would go crazy. Fixing a problem with a component you are presently working on is much easier then fixing it down the line.

October 24, 2004 08:10 PM | John Kopanas commented:

TDD Is Great…Except When It Isn’t http://pluralsight.com/blogs/craig/archive/2004/10/17/2852.aspx

January 19, 2005 09:10 PM | Kevin Sornberger commented:

I might like to disagree with Chris’ statement: “The minimum number of test cases for each bug found in a product would have to be >= 1.”

John brought up a good point in his last post and I would like to add my 2 cents as well. Chris said there is about 156,180 bugs for Gnome right now. I dont believe that this also means that there needs to be a minimum of 156,180 tests as well. What if 1 test was to solve a problem in one area of the code that was causing more problems elsewhere? Wouldn’t it be possible then for 1 test to solve 1 bug which would automatically solve 10 more bugs? Even 100 more bugs (theoritcally speaking)? Maybe not so much once a project has been released but during development I think this could have a more significant effect.

Now if you were writing tests before your code, couldn’t that help you realize something that you were doing wrong earlier on so you wouldnt repeat that mistake again? Thus, resulting in more bugs because of the same mistake.

I am not to familiar with test driven devolpment but it is something that I am going to look into. I think that TDD could be very beneficial to certain projects.

February 7, 2005 10:48 PM | Ness commented:

I mistakenly gave credit to Brooks for a quote which is really belongs to Dijkstra in a post above. My apologies, the full quote is in the end of section 3 in the PDF linked in this comment.

Kevin, do you really believe that fixing one bug will fix n other bugs? If so isn’t it then possible that the opposit can occur. That is, fixing one bug will create n other bugs.
The question then becomes which case is more probable in “real life”?

As for TDD, I think writing test cases is good. You want to know your system works and passes a set of - what I will call - “engineered tests”, but it is physically impossible to exhaustively test large systems this way.

I’m sure TDD works for small components of systems, but what about the integration and system tests on the whole? Does anyone have 10,000 years of computing time at their fingertips for all the required tests? How do you know you’ve covered every test? Even restricting the test space to ‘important or engineered’ tests… How do you know?

Dijkstra wrote about testing over 30 years ago in “Notes On Structured Programming” - 1970. http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD249.PDF

Although he is testing a hardware multiplier I feel the same lessons found on page 9 of the PDF apply to software as well.

I’m not sure or convinced that the obvious “computing is cheap” argument will stand up against the exaustive test case search. Even though computers have improved by orders of magnitude, so have the complexity and demands of our programs so I feel it is acceptable to assume these variables cancel each other out with a fudge factor. It is left as an exercise to the reader to calculate the fudge factor.

You can’t test an entire system. But we already knew that, didn’t we.


Post Your Comments





(note: not displayed)


(note: displayed with comment)

CUSEC 2005

CUSEC is the Canadian Undergraduate Software Engineering Conference created to promote software engineering in canada at the undergraduate level. CUSEC 2005 is being held this year in Ottawa, Canada.

http://2005.cusec.ca

Monthly Newsletter

Sign-up to our monthly newsletter so you can keep up with the latest articles on software engineering and our conference (CUSEC).

sign-up now