Here's some Java code I was writing at the time I first noticed the pattern (November 2007):
That code tests that my implementation of ArrayUtil.shuffle() on an array of doubles works just like the implementation of Collections.shuffle(). One will notice that I called the first block or phase "initialization" and the last one "validation" (which, come to think of it, should have been called "verification" -- more on this at Wikipedia). The block labeled "double-check" should probably have been taken out into its own test./** * Tests the <i>shuffle</i> method against the Collections.shuffle(List<?>, * Random) implementation from which it was derived. */ @Test public void shuffle_AgainstReference ( ) { // { initialization Random randomSource; int length = 20; double[] sourceArray = new double[length]; List<Double> expectedList = new ArrayList<Double> ( length ); for ( int i = 0; i < length; i++ ) { sourceArray[i] = i; expectedList.add ( (double) i ); } // } // { double-check for ( int i = 0; i < length; i++ ) { String message = "Source array is different at index [" + i + "]"; assertEquals ( message, expectedList.get ( i ), sourceArray[i] ); } // } randomSource = new Random ( 42 ); ArrayUtil.shuffle ( sourceArray, randomSource ); randomSource = new Random ( 42 ); Collections.shuffle ( expectedList, randomSource ); // { validation for ( int i = 0; i < length; i++ ) { String message = "Shuffled array is different at index [" + i + "]"; assertEquals ( message, expectedList.get ( i ), sourceArray[i] ); } // } }
I recently noticed the more formalized use in the NamedStringFormatSolution.zip project (more about this project at Phil Haack's Named Formats Redux blog post), where the 3 phases of unit testing were explicitly called out by comments in the code:
The arrange phase is sometimes so trivial that its contents is folded into the act phase, but unless a value is repeated in several tests that it becomes cleaner or less error-prone to extract it out in a constant, it should remain in the test for maximum clarity.[Fact] public void Eval_WithNamedExpressionAndFormat_EvalsPropertyOfExpression() { //arrange var expr = new FormatExpression("{foo:#.##}"); //act string result = expr.Eval(new { foo = 1.23456 }); //assert Assert.Equal("1.23", result); }
So there you have it: the next time you write a test, design it to execute in three distinct phases of arrangement, acting and assertion. Your test will be better designed, easier to read and other maintainers will thank you for it.