001: package junit.framework;
002:
003: import java.lang.reflect.InvocationTargetException;
004: import java.lang.reflect.Method;
005: import java.lang.reflect.Modifier;
006:
007: /**
008: * A test case defines the fixture to run multiple tests. To define a test case<br/>
009: * <ol>
010: * <li>implement a subclass of <code>TestCase</code></li>
011: * <li>define instance variables that store the state of the fixture</li>
012: * <li>initialize the fixture state by overriding {@link #setUp()}</li>
013: * <li>clean-up after a test by overriding {@link #tearDown()}.</li>
014: * </ol>
015: * Each test runs in its own fixture so there
016: * can be no side effects among test runs.
017: * Here is an example:
018: * <pre>
019: * public class MathTest extends TestCase {
020: * protected double fValue1;
021: * protected double fValue2;
022: *
023: * protected void setUp() {
024: * fValue1= 2.0;
025: * fValue2= 3.0;
026: * }
027: * }
028: * </pre>
029: *
030: * For each test implement a method which interacts
031: * with the fixture. Verify the expected results with assertions specified
032: * by calling {@link junit.framework.Assert#assertTrue(String, boolean)} with a boolean.
033: * <pre>
034: * public void testAdd() {
035: * double result= fValue1 + fValue2;
036: * assertTrue(result == 5.0);
037: * }
038: * </pre>
039: *
040: * Once the methods are defined you can run them. The framework supports
041: * both a static type safe and more dynamic way to run a test.
042: * In the static way you override the runTest method and define the method to
043: * be invoked. A convenient way to do so is with an anonymous inner class.
044: * <pre>
045: * TestCase test= new MathTest("add") {
046: * public void runTest() {
047: * testAdd();
048: * }
049: * };
050: * test.run();
051: * </pre>
052: *
053: * The dynamic way uses reflection to implement {@link #runTest()}. It dynamically finds
054: * and invokes a method.
055: * In this case the name of the test case has to correspond to the test method
056: * to be run.
057: * <pre>
058: * TestCase test= new MathTest("testAdd");
059: * test.run();
060: * </pre>
061: *
062: * The tests to be run can be collected into a TestSuite. JUnit provides
063: * different <i>test runners</i> which can run a test suite and collect the results.
064: * A test runner either expects a static method <code>suite</code> as the entry
065: * point to get a test to run or it will extract the suite automatically.
066: * <pre>
067: * public static Test suite() {
068: * suite.addTest(new MathTest("testAdd"));
069: * suite.addTest(new MathTest("testDivideByZero"));
070: * return suite;
071: * }
072: * </pre>
073: * @see TestResult
074: * @see TestSuite
075: */
076: public abstract class TestCase extends Assert implements Test {
077: /**
078: * the name of the test case
079: */
080: private String fName;
081:
082: /**
083: * No-arg constructor to enable serialization. This method
084: * is not intended to be used by mere mortals without calling setName().
085: */
086: public TestCase() {
087: fName = null;
088: }
089:
090: /**
091: * Constructs a test case with the given name.
092: */
093: public TestCase(String name) {
094: fName = name;
095: }
096:
097: /**
098: * Counts the number of test cases executed by run(TestResult result).
099: */
100: public int countTestCases() {
101: return 1;
102: }
103:
104: /**
105: * Creates a default TestResult object
106: *
107: * @see TestResult
108: */
109: protected TestResult createResult() {
110: return new TestResult();
111: }
112:
113: /**
114: * A convenience method to run this test, collecting the results with a
115: * default TestResult object.
116: *
117: * @see TestResult
118: */
119: public TestResult run() {
120: TestResult result = createResult();
121: run(result);
122: return result;
123: }
124:
125: /**
126: * Runs the test case and collects the results in TestResult.
127: */
128: public void run(TestResult result) {
129: result.run(this );
130: }
131:
132: /**
133: * Runs the bare test sequence.
134: * @throws Throwable if any exception is thrown
135: */
136: public void runBare() throws Throwable {
137: Throwable exception = null;
138: setUp();
139: try {
140: runTest();
141: } catch (Throwable running) {
142: exception = running;
143: } finally {
144: try {
145: tearDown();
146: } catch (Throwable tearingDown) {
147: if (exception == null)
148: exception = tearingDown;
149: }
150: }
151: if (exception != null)
152: throw exception;
153: }
154:
155: /**
156: * Override to run the test and assert its state.
157: * @throws Throwable if any exception is thrown
158: */
159: protected void runTest() throws Throwable {
160: assertNotNull("TestCase.fName cannot be null", fName); // Some VMs crash when calling getMethod(null,null);
161: Method runMethod = null;
162: try {
163: // use getMethod to get all public inherited
164: // methods. getDeclaredMethods returns all
165: // methods of this class but excludes the
166: // inherited ones.
167: runMethod = getClass().getMethod(fName, (Class[]) null);
168: } catch (NoSuchMethodException e) {
169: fail("Method \"" + fName + "\" not found");
170: }
171: if (!Modifier.isPublic(runMethod.getModifiers())) {
172: fail("Method \"" + fName + "\" should be public");
173: }
174:
175: try {
176: runMethod.invoke(this );
177: } catch (InvocationTargetException e) {
178: e.fillInStackTrace();
179: throw e.getTargetException();
180: } catch (IllegalAccessException e) {
181: e.fillInStackTrace();
182: throw e;
183: }
184: }
185:
186: /**
187: * Sets up the fixture, for example, open a network connection.
188: * This method is called before a test is executed.
189: */
190: protected void setUp() throws Exception {
191: }
192:
193: /**
194: * Tears down the fixture, for example, close a network connection.
195: * This method is called after a test is executed.
196: */
197: protected void tearDown() throws Exception {
198: }
199:
200: /**
201: * Returns a string representation of the test case
202: */
203: @Override
204: public String toString() {
205: return getName() + "(" + getClass().getName() + ")";
206: }
207:
208: /**
209: * Gets the name of a TestCase
210: * @return the name of the TestCase
211: */
212: public String getName() {
213: return fName;
214: }
215:
216: /**
217: * Sets the name of a TestCase
218: * @param name the name to set
219: */
220: public void setName(String name) {
221: fName = name;
222: }
223: }
|