One Unit Test Ata Time

Should we write only one UnitTest at a time, or is it OK to write several before writing the code that fixes them?

When doing "CodeUnitTestFirst," an ExtremeProgramming practice, it's assumed that you will write one UnitTest at a time, and then write code until it works before writing the next UnitTest.

See WriteJustOneTest


[This topic came up in UnitTestsReconsidered (and the discussion was moved from there to here).]

TestFirstProgramming forces you to work on only one thing at a time.

If you habitually write one test and then make it work, it keeps you from having so many balls in the air. It's not the only way to accomplish that, but it is one way. -- RonJeffries

I rebut it's not the tests that are keeping you working on only one thing at a time, it is you. Nothing about UnitTests keeps you working on one thing at a time because it's possible to write all UnitTests for one method before you implement the method.

I didn't say the tests keep you working on only one thing at a time, I said writing one test and making it works keeps you working on one thing at a time. I do agree, of course, that it is you who are doing it. Did it seem that I thought it was some mystical force? ;->

To this, PhilGoodwin says...
I like to keep all but the most current test commented out so I really am only working on one method (or group of methods) at a time. It's kind of a pain, but it lets me avoid starting the implementations of more than one method at a time.

Yes, but once again this is something you yourself have done. In actuality, this is an ExtremeProgramming practice. Thus, we can reject this line of support completely. Not to say that it's a bad practice. It's quite good. However, I refer you to RobertDiFalco's habits:

You implement the methods as they are required. For example, when creating a needed abstraction, you will usually start with the most important method or most needed method. Instead, you create a TestMethod for it first. Then, if you discover (as does frequently happen) that this method depends on another method that is not yet implemented, you go to that method and create its TestMethod and implement it....and so on. In a way, it's like a best-fit algorithm and usually leads to the most efficient path for implementing the abstraction. -- RobertDiFalco

Another approach to this is described at WriteJustOneTest.

To which I point out that my practice is to implement the most obvious method first, realize it needs to call a non-existent method and then code that next. This is exactly the same as RobertDiFalco, except I don't write the tests first (necessarily; sometimes I do.) Moreover, this exemplifies my point about the calling context defining the interface.

As you might see, I don't need a UnitTest for the new method if I have a FunctionalTest somewhere lower in the call stack checking the whole thing. True, errors may be introduced at several points that never get discovered, but at a certain point the value of discovering non-triggerable failures is outweighed by the mud created by excessive testing. (See CompleteCoverageIsExpensive.)

Perhaps if the original argument had been "helps you to work" rather than "forces you to work" it would be less contentious?

Agreed. Just like CrcCards don't force you to keep things simple, but they help you to keep things simple by being physically difficult to use.


I don't claim to be doing ExtremeProgramming, but I often write a number of low level automated regression tests at once.

When writing the code first, you need to do it that way, but it requires a lot of discipline.

When doing CodeUnitTestFirst, I find that writing lots of tests first helps me focus on what I want accomplished. The tests give me a place to put things I think about so I don't forget them.

Now, in reality, I do experience some pain because I usually test with assert statements instead of an StarUnit library -- so any single failure brings all testing to a halt. Surprisingly, this has not turned out to be a problem in practice: because the "slew of tests" I wrote all at once all relate to a single class or function, they all work once the class/function is successfully written. If I get delayed or distracted, I can always comment out tests that are getting annoying (with a "TODO Comment" as a reminder -- see FixmeComment).

-- JeffGrigg

I outline a bunch of tests before I start as items in a list. Then I implement the first one, make it work, refactor, etc. I used to implement a bunch at a time, but then I programmed a little with Ward and realized that all those tests implemented against a speculative interface made changing the interface harder. The reduced certainty of only having the tests outlined instead of implemented is more than made up for by the additional speed of evolving the interface. -- KentBeck

I use this method too. For me at least, CodeUnitTestFirst tends to test my interfaces as well as their implementation. Interface bugs are fixed by changing the interface -- a lot harder when you have a bunch of tests. Maybe my interfaces start off too speculatively -- but it works for me. As stated earlier, this is also a good time to NarrowTheInterface. -- RobertDiFalco

See WhatIsReworking for another way to work.


I think this may be a superior rule to CodeUnitTestFirst. I found that when I started doing one thing at a time, I could picture both the change and the test simultaneously. At that point, it doesn't really matter which one you physically type in first. With C++, it is just a whole lot easier to define the function prototype before trying to build test code that links to it. I believe the key concept is working in extremely small increments and adding just one thing at a time. -- WayneMack


CategoryTesting


EditText of this page (last edited September 16, 2003) or FindPage with title or text search