1 package junit.framework;
2
3 import java.io.PrintWriter;
4 import java.io.StringWriter;
5 import java.lang.reflect.Constructor;
6 import java.lang.reflect.InvocationTargetException;
7 import java.lang.reflect.Method;
8 import java.lang.reflect.Modifier;
9 import java.util.ArrayList;
10 import java.util.Enumeration;
11 import java.util.List;
12 import java.util.Vector;
13
14 import org.junit.internal.MethodSorter;
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class TestSuite implements Test {
45
46
47
48
49
50 static public Test createTest(Class<?> theClass, String name) {
51 Constructor<?> constructor;
52 try {
53 constructor = getTestConstructor(theClass);
54 } catch (NoSuchMethodException e) {
55 return warning("Class " + theClass.getName() + " has no public constructor TestCase(String name) or TestCase()");
56 }
57 Object test;
58 try {
59 if (constructor.getParameterTypes().length == 0) {
60 test = constructor.newInstance(new Object[0]);
61 if (test instanceof TestCase) {
62 ((TestCase) test).setName(name);
63 }
64 } else {
65 test = constructor.newInstance(new Object[]{name});
66 }
67 } catch (InstantiationException e) {
68 return (warning("Cannot instantiate test case: " + name + " (" + exceptionToString(e) + ")"));
69 } catch (InvocationTargetException e) {
70 return (warning("Exception in constructor: " + name + " (" + exceptionToString(e.getTargetException()) + ")"));
71 } catch (IllegalAccessException e) {
72 return (warning("Cannot access test case: " + name + " (" + exceptionToString(e) + ")"));
73 }
74 return (Test) test;
75 }
76
77
78
79
80
81 public static Constructor<?> getTestConstructor(Class<?> theClass) throws NoSuchMethodException {
82 try {
83 return theClass.getConstructor(String.class);
84 } catch (NoSuchMethodException e) {
85
86 }
87 return theClass.getConstructor();
88 }
89
90
91
92
93 public static Test warning(final String message) {
94 return new TestCase("warning") {
95 @Override
96 protected void runTest() {
97 fail(message);
98 }
99 };
100 }
101
102
103
104
105 private static String exceptionToString(Throwable e) {
106 StringWriter stringWriter = new StringWriter();
107 PrintWriter writer = new PrintWriter(stringWriter);
108 e.printStackTrace(writer);
109 return stringWriter.toString();
110 }
111
112 private String fName;
113
114 private Vector<Test> fTests = new Vector<Test>(10);
115
116
117
118
119 public TestSuite() {
120 }
121
122
123
124
125
126
127
128 public TestSuite(final Class<?> theClass) {
129 addTestsFromTestCase(theClass);
130 }
131
132 private void addTestsFromTestCase(final Class<?> theClass) {
133 fName = theClass.getName();
134 try {
135 getTestConstructor(theClass);
136 } catch (NoSuchMethodException e) {
137 addTest(warning("Class " + theClass.getName() + " has no public constructor TestCase(String name) or TestCase()"));
138 return;
139 }
140
141 if (!Modifier.isPublic(theClass.getModifiers())) {
142 addTest(warning("Class " + theClass.getName() + " is not public"));
143 return;
144 }
145
146 Class<?> superClass = theClass;
147 List<String> names = new ArrayList<String>();
148 while (Test.class.isAssignableFrom(superClass)) {
149 for (Method each : MethodSorter.getDeclaredMethods(superClass)) {
150 addTestMethod(each, names, theClass);
151 }
152 superClass = superClass.getSuperclass();
153 }
154 if (fTests.size() == 0) {
155 addTest(warning("No tests found in " + theClass.getName()));
156 }
157 }
158
159
160
161
162
163
164 public TestSuite(Class<? extends TestCase> theClass, String name) {
165 this(theClass);
166 setName(name);
167 }
168
169
170
171
172 public TestSuite(String name) {
173 setName(name);
174 }
175
176
177
178
179
180
181 public TestSuite(Class<?>... classes) {
182 for (Class<?> each : classes) {
183 addTest(testCaseForClass(each));
184 }
185 }
186
187 private Test testCaseForClass(Class<?> each) {
188 if (TestCase.class.isAssignableFrom(each)) {
189 return new TestSuite(each.asSubclass(TestCase.class));
190 } else {
191 return warning(each.getCanonicalName() + " does not extend TestCase");
192 }
193 }
194
195
196
197
198
199
200 public TestSuite(Class<? extends TestCase>[] classes, String name) {
201 this(classes);
202 setName(name);
203 }
204
205
206
207
208 public void addTest(Test test) {
209 fTests.add(test);
210 }
211
212
213
214
215 public void addTestSuite(Class<? extends TestCase> testClass) {
216 addTest(new TestSuite(testClass));
217 }
218
219
220
221
222 public int countTestCases() {
223 int count = 0;
224 for (Test each : fTests) {
225 count += each.countTestCases();
226 }
227 return count;
228 }
229
230
231
232
233
234
235 public String getName() {
236 return fName;
237 }
238
239
240
241
242 public void run(TestResult result) {
243 for (Test each : fTests) {
244 if (result.shouldStop()) {
245 break;
246 }
247 runTest(each, result);
248 }
249 }
250
251 public void runTest(Test test, TestResult result) {
252 test.run(result);
253 }
254
255
256
257
258
259
260 public void setName(String name) {
261 fName = name;
262 }
263
264
265
266
267 public Test testAt(int index) {
268 return fTests.get(index);
269 }
270
271
272
273
274 public int testCount() {
275 return fTests.size();
276 }
277
278
279
280
281 public Enumeration<Test> tests() {
282 return fTests.elements();
283 }
284
285
286
287 @Override
288 public String toString() {
289 if (getName() != null) {
290 return getName();
291 }
292 return super.toString();
293 }
294
295 private void addTestMethod(Method m, List<String> names, Class<?> theClass) {
296 String name = m.getName();
297 if (names.contains(name)) {
298 return;
299 }
300 if (!isPublicTestMethod(m)) {
301 if (isTestMethod(m)) {
302 addTest(warning("Test method isn't public: " + m.getName() + "(" + theClass.getCanonicalName() + ")"));
303 }
304 return;
305 }
306 names.add(name);
307 addTest(createTest(theClass, name));
308 }
309
310 private boolean isPublicTestMethod(Method m) {
311 return isTestMethod(m) && Modifier.isPublic(m.getModifiers());
312 }
313
314 private boolean isTestMethod(Method m) {
315 return m.getParameterTypes().length == 0 &&
316 m.getName().startsWith("test") &&
317 m.getReturnType().equals(Void.TYPE);
318 }
319 }