
628
Chapter 24 Test Organization Patterns
which Test Methods should go into each one. If some Testcase Classes will end
up being smaller than others, it makes the job easier if we start by building the
smaller classes. Next, we do an Extract Class [Fowler] refactoring to create
one of the new Testcase Classes and give it a name that describes the feature it
exercises. Then, we do a Move Method [Fowler] refactoring (or a simple “cut
and paste”) on each Test Method that belongs in this new class along with any
instance variables it uses.
We repeat this process until we are down to just one feature in the original
Testcase Class; we then rename that class based on the feature it exercises. At
this point, each of the Testcase Classes should compile and run—but we still
aren’t completely done. To get the full benefi t of the Testcase Class per Feature
pattern, we have one fi nal step to carry out. We should do a Rename Method
[Fowler] refactoring on each of the Test Methods to better refl ect what the Test
Method is verifying. As part of this refactoring, we can remove any mention
of the feature being exercised from each Test Method name—that informa-
tion should be captured in the name of the Testcase Class. This leaves us with
“room” to include both the starting state (the fi xture) and the expected result
in the method name. If we have multiple tests for each feature with different
method arguments, we’ll need to fi nd a way to include those aspects of the
test conditions in the method name, too.
Another way to perform this refactoring is simply to make copies of the orig-
inal Testcase Class and rename them as described above. Then we simply delete
the Test Methods that aren’t relevant for each class. We do need to be careful
that we don’t delete all copies of a Test Method; a less critical oversight is to
leave a copy of the same method in several Testcase Classes. We can avoid both
of the potential errors by making one copy of the original Testcase Class for
each of the features and rename them as described above. Then we simply de-
lete the Test Methods that aren’t relevant for each class. When we are done, we
simply delete the original Testcase Class.
Example: Testcase Class per Feature
In this example, we have converted the previously mentioned set of tests to use
Testcase Class per Feature.
public class TestScheduleFlight extends TestCase {
public void testUnscheduled_shouldEndUpInScheduled()
throws Exception {
Flight flight = FlightTestHelper.
getAnonymousFlightInUnscheduledState();
flight.schedule();
assertTrue( "isScheduled()", flight.isScheduled());
Testcase
Class per
Feature