1 package junit.framework;
2
3 import java.util.Vector;
4 import java.util.Enumeration;
5 import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.*;
6 import java.lang.reflect.Constructor;
7
8 /**
9 * A <code>TestSuite</code> is a <code>Composite</code> of Tests.
10 * It runs a collection of test cases. Here is an example using
11 * the dynamic test definition.
12 * <pre>
13 * TestSuite suite= new TestSuite();
14 * suite.addTest(new MathTest("testAdd"));
15 * suite.addTest(new MathTest("testDivideByZero"));
16 * </pre>
17 * Alternatively, a TestSuite can extract the tests to be run automatically.
18 * To do so you pass the class of your TestCase class to the
19 * TestSuite constructor.
20 * <pre>
21 * TestSuite suite= new TestSuite(MathTest.class);
22 * </pre>
23 * This constructor creates a suite with all the methods
24 * starting with "test" that take no arguments.
25 *
26 * @see Test
27 */
28 public class TestSuite implements Test {
29
30 private Vector fTests= new Vector(10);
31 private String fName;
|
32
|
33 /**
34 * Constructs an empty TestSuite.
35 */
36 public TestSuite() {
37 }
|
38
39 /**
|
40 * Constructs a TestSuite from the given class with the given name.
41 * @see TestSuite#TestSuite(Class)
42 */
43 public TestSuite(Class theClass, String name) {
44 this(theClass);
45 setName(name);
|
46 > }
47 >
48 > /**
|
49 * Constructs a TestSuite from the given class. Adds all the methods
50 * starting with "test" as test cases to the suite.
51 * Parts of this method was written at 2337 meters in the Hüffihütte,
52 * Kanton Uri
53 */
54 public TestSuite(final Class theClass) {
55 fName= theClass.getName();
|
56 try {
57 getTestConstructor(theClass); // Avoid generating multiple error messages
|
58 } catch (NoSuchMethodException e) {
|
59 addTest(warning("Class "+theClass.getName()+" has no public constructor TestCase(String name) or TestCase()"));
60 return;
|
61 > }
62 >
|
63 if (!Modifier.isPublic(theClass.getModifiers())) {
64 addTest(warning("Class "+theClass.getName()+" is not public"));
|
65 return;
|
66 > }
67 >
|
68 Class superClass= theClass;
69 Vector names= new Vector();
|
70 while (Test.class.isAssignableFrom(superClass)) {
71 Method[] methods= superClass.getDeclaredMethods();
72 for (int i= 0; i < methods.length; i++) {
73 addTestMethod(methods[i], names, theClass);
74 }
75 superClass= superClass.getSuperclass();
|
76 }
|
77 if (fTests.size() == 0)
|
78 addTest(warning("No tests found in "+theClass.getName()));
|
79 }
80
81 /**
|
82 * Constructs an empty TestSuite.
83 */
84 public TestSuite(String name) {
85 setName(name);
|
86 }
87
88 /**
|
89 * Adds a test to the suite.
90 */
91 public void addTest(Test test) {
92 fTests.addElement(test);
93 }
|
94
95 /**
|
96 * Adds the tests from the given class to the suite
97 */
98 public void addTestSuite(Class testClass) {
99 addTest(new TestSuite(testClass));
100 }
|
101
102 private void addTestMethod(Method m, Vector names, Class theClass) {
|
103 String name= m.getName();
104 if (names.contains(name))
|
105 return;
106 if (! isPublicTestMethod(m)) {
107 if (isTestMethod(m))
108 addTest(warning("Test method isn't public: "+m.getName()));
109 return;
110 }
111 names.addElement(name);
|
112 addTest(createTest(theClass, name));
|
113 }
114
115 /**
|
116 * ...as the moon sets over the early morning Merlin, Oregon
117 * mountains, our intrepid adventurers type...
118 */
119 static public Test createTest(Class theClass, String name) {
120 Constructor constructor;
121 try {
122 constructor= getTestConstructor(theClass);
123 } catch (NoSuchMethodException e) {
|
124 return warning("Class "+theClass.getName()+" has no public constructor TestCase(String name) or TestCase()");
125 }
|
126 > Object test;
|
127 try {
128 if (constructor.getParameterTypes().length == 0) {
129 test= constructor.newInstance(new Object[0]);
|
130 if (test instanceof TestCase)
131 ((TestCase) test).setName(name);
132 } else {
133 test= constructor.newInstance(new Object[]{name});
|
134 }
|
135 } catch (InstantiationException e) {
|
136 return(warning("Cannot instantiate test case: "+name+" ("+exceptionToString(e)+")"));
|
137 } catch (InvocationTargetException e) {
|
138 > return(warning("Exception in constructor: "+name+" ("+exceptionToString(e.getTargetException())+")"));
|
139 } catch (IllegalAccessException e) {
|
140 > return(warning("Cannot access test case: "+name+" ("+exceptionToString(e)+")"));
|
141 }
|
142 > return (Test) test;
|
143 }
|
144
|
145 /**
146 * Converts the stack trace into a string
147 */
148 private static String exceptionToString(Throwable t) {
149 StringWriter stringWriter= new StringWriter();
150 PrintWriter writer= new PrintWriter(stringWriter);
|
151 > t.printStackTrace(writer);
152 > return stringWriter.toString();
153 >
154 > }
|
155
156 /**
157 * Counts the number of test cases that will be run by this test.
158 */
159 public int countTestCases() {
160 int count= 0;
161 for (Enumeration e= tests(); e.hasMoreElements(); ) {
|
162 Test test= (Test)e.nextElement();
163 count= count + test.countTestCases();
164 }
165 return count;
|
166 }
|
167
|
168 /**
169 * Gets a constructor which takes a single String as
170 * its argument or a no arg constructor.
171 */
172 public static Constructor getTestConstructor(Class theClass) throws NoSuchMethodException {
173 Class[] args= { String.class };
174 try {
|
175 return theClass.getConstructor(args);
|
176 } catch (NoSuchMethodException e) {
|
177 // fall through
178 }
|
179 return theClass.getConstructor(new Class[0]);
|
180 }
181
|
182 private boolean isPublicTestMethod(Method m) {
183 return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
184 }
|
185
|
186 private boolean isTestMethod(Method m) {
187 String name= m.getName();
188 Class[] parameters= m.getParameterTypes();
|
189 Class returnType= m.getReturnType();
190 return parameters.length == 0 && name.startsWith("test") && returnType.equals(Void.TYPE);
191 }
192
|
193 /**
194 * Runs the tests and collects their result in a TestResult.
195 */
196 public void run(TestResult result) {
197 for (Enumeration e= tests(); e.hasMoreElements(); ) {
198 if (result.shouldStop() )
|
199 break;
200 Test test= (Test)e.nextElement();
|
201 > runTest(test, result);
|
202 }
203 }
|
204
|
205 public void runTest(Test test, TestResult result) {
|
206 test.run(result);
207 }
|
208
209 /**
|
210 * Returns the test at the given index
211 */
212 public Test testAt(int index) {
213 return (Test)fTests.elementAt(index);
214 }
|
215 >
|
216 /**
217 * Returns the number of tests in this suite
218 */
219 public int testCount() {
220 return fTests.size();
221 }
|
222
|
223 /**
224 * Returns the tests as an enumeration
225 */
226 public Enumeration tests() {
227 return fTests.elements();
228 }
|
229
|
230 /**
231 */
232 public String toString() {
233 if (getName() != null)
234 return getName();
|
235 > return super.toString();
236 > }
237 >
|
238 /**
239 * Sets the name of the suite.
240 * @param name The name to set
241 */
242 public void setName(String name) {
243 fName= name;
244 }
|
245
246 /**
|
247 * Returns the name of the suite. Not all
248 * test suites have a name and this method
249 * can return null.
250 */
251 public String getName() {
252 return fName;
253 }
|
254 >
|
255 /**
256 * Returns a test which will fail and log a warning message.
257 */
258 private static Test warning(final String message) {
259 return new TestCase("warning") {
260 protected void runTest() {
|
261 fail(message);
262 }
263 };
|
264 > }
|
265 } |