1 package junit.framework; 2 3 import java.lang.reflect.*; 4 5 /** 6 * A test case defines the fixture to run multiple tests. To define a test case<br> 7 * 1) implement a subclass of TestCase<br> 8 * 2) define instance variables that store the state of the fixture<br> 9 * 3) initialize the fixture state by overriding <code>setUp</code><br> 10 * 4) clean-up after a test by overriding <code>tearDown</code>.<br> 11 * Each test runs in its own fixture so there 12 * can be no side effects among test runs. 13 * Here is an example: 14 * <pre> 15 * public class MathTest extends TestCase { 16 * protected double fValue1; 17 * protected double fValue2; 18 * 19 * protected void setUp() { 20 * fValue1= 2.0; 21 * fValue2= 3.0; 22 * } 23 * } 24 * </pre> 25 * 26 * For each test implement a method which interacts 27 * with the fixture. Verify the expected results with assertions specified 28 * by calling <code>assertTrue</code> with a boolean. 29 * <pre> 30 * public void testAdd() { 31 * double result= fValue1 + fValue2; 32 * assertTrue(result == 5.0); 33 * } 34 * </pre> 35 * Once the methods are defined you can run them. The framework supports 36 * both a static type safe and more dynamic way to run a test. 37 * In the static way you override the runTest method and define the method to 38 * be invoked. A convenient way to do so is with an anonymous inner class. 39 * <pre> 40 * TestCase test= new MathTest("add") { 41 * public void runTest() { 42 * testAdd(); 43 * } 44 * }; 45 * test.run(); 46 * </pre> 47 * The dynamic way uses reflection to implement <code>runTest</code>. It dynamically finds 48 * and invokes a method. 49 * In this case the name of the test case has to correspond to the test method 50 * to be run. 51 * <pre> 52 * TestCase= new MathTest("testAdd"); 53 * test.run(); 54 * </pre> 55 * The tests to be run can be collected into a TestSuite. JUnit provides 56 * different <i>test runners</i> which can run a test suite and collect the results. 57 * A test runner either expects a static method <code>suite</code> as the entry 58 * point to get a test to run or it will extract the suite automatically. 59 * <pre> 60 * public static Test suite() { 61 * suite.addTest(new MathTest("testAdd")); 62 * suite.addTest(new MathTest("testDivideByZero")); 63 * return suite; 64 * } 65 * </pre> 66 * @see TestResult 67 * @see TestSuite 68 */ 69 70 public abstract class TestCase extends Assert implements Test { 71 /** 72 * the name of the test case 73 */ 74 private String fName; 75 76 /** 77 * No-arg constructor to enable serialization. This method 78 * is not intended to be used by mere mortals without calling setName(). 79 */ 80 public TestCase() { 81 fName= null; 82 } 83 /** 84 * Constructs a test case with the given name. 85 */ 86 public TestCase(String name) { 87 fName= name; 88 } 89 /** 90 * Counts the number of test cases executed by run(TestResult result). 91 */ 92 public int countTestCases() { 93 return 1; 94 } 95 /** 96 * Creates a default TestResult object 97 * 98 * @see TestResult 99 */ 100 protected TestResult createResult() { 101 return new TestResult(); 102 } 103 /** 104 * A convenience method to run this test, collecting the results with a 105 * default TestResult object. 106 * 107 * @see TestResult 108 */ 109 public TestResult run() { 110 TestResult result= createResult(); 111 run(result); 112 return result; 113 } 114 /** 115 * Runs the test case and collects the results in TestResult. 116 */ 117 public void run(TestResult result) { 118 result.run(this); 119 } 120 /** 121 * Runs the bare test sequence. 122 * @exception Throwable if any exception is thrown 123 */ 124 public void runBare() throws Throwable { 125 setUp(); 126 try { 127 runTest(); 128 } 129 finally { 130 tearDown(); 131 } 132 } 133 /** 134 * Override to run the test and assert its state. 135 * @exception Throwable if any exception is thrown 136 */ 137 protected void runTest() throws Throwable { 138 assertNotNull(fName); 139 Method runMethod= null; 140 try { 141 // use getMethod to get all public inherited 142 // methods. getDeclaredMethods returns all 143 // methods of this class but excludes the 144 // inherited ones. 145 runMethod= getClass().getMethod(fName, (Class[]) null); 146 } catch (NoSuchMethodException e) { 147 fail("Method \""+fName+"\" not found"); 148 } 149 if (!Modifier.isPublic(runMethod.getModifiers())) { 150 fail("Method \""+fName+"\" should be public"); 151 } 152 153 try { 154 runMethod.invoke(this, (Object[]) new Class[0]); 155 } 156 catch (InvocationTargetException e) { 157 e.fillInStackTrace(); 158 throw e.getTargetException(); 159 } 160 catch (IllegalAccessException e) { 161 e.fillInStackTrace(); 162 throw e; 163 } 164 } 165 /** 166 * Sets up the fixture, for example, open a network connection. 167 * This method is called before a test is executed. 168 */ 169 protected void setUp() throws Exception { 170 } 171 /** 172 * Tears down the fixture, for example, close a network connection. 173 * This method is called after a test is executed. 174 */ 175 protected void tearDown() throws Exception { 176 } 177 /** 178 * Returns a string representation of the test case 179 */ 180 public String toString() { 181 return getName() + "(" + getClass().getName() + ")"; 182 } 183 /** 184 * Gets the name of a TestCase 185 * @return returns a String 186 */ 187 public String getName() { 188 return fName; 189 } 190 /** 191 * Sets the name of a TestCase 192 * @param name The name to set 193 */ 194 public void setName(String name) { 195 fName= name; 196 } 197 } 198