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.
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 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