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