'''Patterns''' *TestFirstByIntention, CodeUnitTestFirst *TestEverythingThatCouldPossiblyBreak *HaveOnlyOneFailingTestAtaTime, OneUnitTestAtaTime *GrowThenSplit *SplitThenGrow *AvoidSpeculativeDesign *TestEveryRefactoring *WriteTestsBackwards Note that unit testing in XP is both a testing and design strategy. ---- There are different approaches in how to test-code-refactor a complex class hierarchy. Some people are in favor of the nested approach, while others are not. Each of them pose advantages and disadvantages. When is each applicable? For example, let's say you have to code class A, which you THINK is going to need classes B, C, D, and E. Here are some choices: Note: test X implies testing class X and having it pass 100% Observation: Maybe THINKING you'll need classes B-E is the mistake? a) Serial approach write test E, write E, test E write test D, write D, test D write test C, write C, test C write test B, write B, test B write test A, write A, test A Advantages: ??? Disadvantages: Violates YAGNI ''How does this violate YAGNI?'' It violates YAGNI because you THINK you need classes B-E, but you should not implement them until another class actually needs them. b) Nested approach write test A, write A write test B, write B write test C, write C write test D, write D write test E, write E, test E test D test C test B test A Advantages: ??? Disadvantages: Time between implementation and testing could be too extensive, violates YAGNI, nesting is hard to manage c) Nested approach with partial implementation write test A, write A (just enough to pass test), test A write test B, write B (just enough to pass test), test B write test C, write C (just enough to pass test), test C write test D, write D, (just enough to pass test) write test E, write E (fully), test E write D (fully), test D write C (fully), test C write B (fully), test B write A (fully), test A Advantages: ??? Disadvantages: Violates YAGNI, nesting is hard to manage d) Partial nesting approach write test A, write A write test B, write B, test B write test C, write C, test C write test D, write D, test D write test E, write E, test E test A Advantages: ??? Disadvantages: Dependencies between classes are not tested (Remember class B calls class C, where is this tested?), violates YAGNI. e) Solution proposed by HagbardCeline (http://groups.yahoo.com/group/extremeprogramming/message/23907) Write test A. Write enough of A to know how I call B. Write test B. Write enough of B to know how I call C. Write test C. Write enough of C to know how I call D. Write test D. Write enough of D to know how I call E. Write test E. Write E. While Test E fails, continue working on E. Write the rest of D. While test D fails, continue working on D. Write the rest of C. While test C fails, continue working on C. Write the rest of B. While test B fails, continue working on B. Write the rest of A. While test A fails, continue working on A. Advantages: The A-E are all written test-first and all pass at 100% before I move on. Disadvantages: Nesting is hard to manage. If you only THINK you need B, C, D and E then write A with the parts you think you need represented as attributes or methods of A. (I assume that because thinking about A makes you think about B, C, D and E they, or some parts of them, fall "inside" the "A Space" in some way). When A becomes unwieldy or some good reason appears to factor out one of the MAYBE classes, do it and write tests for the new class and change the tests for the refactored A. Until then you don't have the design information to worry about writing them. If you do have it, then you KNOW you will need them all and the problem is the same as anytime you know you need to write more than one related class. (Interesting, what is clearly implied is that the tests themselves are in some way part of the "code" of the application and hold design information about it.) -- KennethTyler Kenneth, to summarize, is this what you mean: f) Solution proposed by IljaPreuss (http://groups.yahoo.com/group/extremeprogramming/message/15771) write test A, write A, test A refactor A to A, B, C, D & E Advantages: ??? Disadvantages: ??? ---- There seem to be two forces at play here: 1. HaveOnlyOneFailingTestAtaTime 2. Design for the immediate task at hand, that is AvoidSpeculativeDesign. Specifically YAGNI in terms of actually needing classes B, C, D, and E. The serial approach satisfies 1 but fails at 2. The nested approach fails at both 1 and 2. The partial nested approach is closer to satisfying 1 but still fails and also fails at 2. Hagbard's approach would seem to be a better variant of the nested approach. What KennethTyler describes satisfies both forces but is not exactly equivalent to the IljaPreub approach. while task A is not completed write test for task A write enough to pass test if classes becomes unwieldly refactor The main point is that the refactoring doesn't all happen at the end and the initial tests are more for the intended task than the implemented classes. I also add a bunch of white box tests at the end to convince myself that the implemented classes work correctly but those aren't TestFirstByIntention kind of tests. -- JasonYip ---- I call this one GrowThenSplit. I describe it a bit at http://www.xprogramming.com/xpmag/tfd2.htm. -- MichaelFeathers ---- Egroups Threads: http://groups.yahoo.com/group/extremeprogramming/message/15342 http://groups.yahoo.com/group/extremeprogramming/message/15370 http://groups.yahoo.com/group/extremeprogramming/message/16139 http://groups.yahoo.com/group/extremeprogramming/message/16164 http://groups.yahoo.com/group/extremeprogramming/message/16171 http://groups.yahoo.com/group/extremeprogramming/message/16181 ---- See ExtremeProgrammingImplementationIssues