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