KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > test > EclipseTestRunner


1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.test;
12
13 import java.io.ByteArrayOutputStream JavaDoc;
14 import java.io.File JavaDoc;
15 import java.io.FileInputStream JavaDoc;
16 import java.io.FileOutputStream JavaDoc;
17 import java.io.IOException JavaDoc;
18 import java.io.OutputStream JavaDoc;
19 import java.io.PrintStream JavaDoc;
20 import java.lang.reflect.InvocationTargetException JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.util.Enumeration JavaDoc;
23 import java.util.Hashtable JavaDoc;
24 import java.util.Properties JavaDoc;
25 import java.util.Vector JavaDoc;
26 import junit.framework.AssertionFailedError;
27 import junit.framework.Test;
28 import junit.framework.TestListener;
29 import junit.framework.TestResult;
30 import junit.framework.TestSuite;
31 import org.apache.tools.ant.BuildException;
32 import org.apache.tools.ant.Project;
33 import org.apache.tools.ant.taskdefs.optional.junit.FormatterElement;
34 import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter;
35 import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;
36 import org.eclipse.core.runtime.Platform;
37
38 /**
39  * A TestRunner for JUnit that supports Ant JUnitResultFormatters
40  * and running tests inside Eclipse.
41  * Example call: EclipseTestRunner -classname junit.samples.SimpleTest formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter
42  */

43 public class EclipseTestRunner implements TestListener {
44     class TestFailedException extends Exception JavaDoc {
45
46         private static final long serialVersionUID = 6009335074727417445L;
47
48         TestFailedException(String JavaDoc message) {
49             super(message);
50         }
51     }
52     /**
53      * No problems with this test.
54      */

55     public static final int SUCCESS= 0;
56     /**
57      * Some tests failed.
58      */

59     public static final int FAILURES= 1;
60     /**
61      * An error occured.
62      */

63     public static final int ERRORS= 2;
64     
65     private static final String JavaDoc SUITE_METHODNAME= "suite";
66     /**
67      * debug mode
68      */

69     private boolean debug= false;
70     /**
71      * The current test result
72      */

73     private TestResult fTestResult;
74     /**
75      * The name of the plugin containing the test
76      */

77     private String JavaDoc fTestPluginName;
78     /**
79      * The corresponding testsuite.
80      */

81     private Test fSuite;
82     /**
83      * Formatters from the command line.
84      */

85     private static Vector JavaDoc fgFromCmdLine= new Vector JavaDoc();
86     /**
87      * Holds the registered formatters.
88      */

89     private Vector JavaDoc formatters= new Vector JavaDoc();
90     /**
91      * Do we stop on errors.
92      */

93     private boolean fHaltOnError= false;
94     /**
95      * Do we stop on test failures.
96      */

97     private boolean fHaltOnFailure= false;
98     /**
99      * The TestSuite we are currently running.
100      */

101     private JUnitTest fJunitTest;
102     /**
103      * output written during the test
104      */

105     private PrintStream JavaDoc fSystemError;
106     /**
107      * Error output during the test
108      */

109     private PrintStream JavaDoc fSystemOut;
110     /**
111      * Exception caught in constructor.
112      */

113     private Exception JavaDoc fException;
114     /**
115      * Returncode
116      */

117     private int fRetCode= SUCCESS;
118     
119     /**
120      * The main entry point (the parameters are not yet consistent with
121      * the Ant JUnitTestRunner, but eventually they should be).
122      * Parameters<pre>
123      * -className: the name of the testSuite
124      * -testPluginName: the name of the containing plugin
125      * haltOnError: halt test on errors?
126      * haltOnFailure: halt test on failures?
127      * -testlistener listenerClass: deprecated
128      * print a warning that this option is deprecated
129      * formatter: a JUnitResultFormatter given as classname,filename.
130      * If filename is ommitted, System.out is assumed.
131      * </pre>
132      */

133     public static void main(String JavaDoc[] args) throws IOException JavaDoc {
134         System.exit(run(args));
135     }
136     public static int run(String JavaDoc[] args) throws IOException JavaDoc {
137         String JavaDoc className= null;
138         String JavaDoc testPluginName= null;
139         
140         boolean haltError = false;
141         boolean haltFail = false;
142         
143         Properties JavaDoc props = new Properties JavaDoc();
144         
145         int startArgs= 0;
146         if (args.length > 0) {
147             // support the JUnit task commandline syntax where
148
// the first argument is the name of the test class
149
if (!args[0].startsWith("-")) {
150                 className= args[0];
151                 startArgs++;
152             }
153         }
154         for (int i= startArgs; i < args.length; i++) {
155             if (args[i].toLowerCase().equals("-classname")) {
156                 if (i < args.length-1)
157                     className= args[i+1];
158                 i++;
159             } else if (args[i].toLowerCase().equals("-testpluginname")) {
160                 if (i < args.length-1)
161                     testPluginName= args[i+1];
162                 i++;
163             } else if (args[i].startsWith("haltOnError=")) {
164                 haltError= Project.toBoolean(args[i].substring(12));
165             } else if (args[i].startsWith("haltOnFailure=")) {
166                 haltFail = Project.toBoolean(args[i].substring(14));
167             } else if (args[i].startsWith("formatter=")) {
168                 try {
169                     createAndStoreFormatter(args[i].substring(10));
170                 } catch (BuildException be) {
171                     System.err.println(be.getMessage());
172                     return ERRORS;
173                 }
174             } else if (args[i].startsWith("propsfile=")) {
175                 FileInputStream JavaDoc in = new FileInputStream JavaDoc(args[i].substring(10));
176                 props.load(in);
177                 in.close();
178             } else if (args[i].equals("-testlistener")) {
179                 System.err.println("The -testlistener option is no longer supported\nuse the formatter= option instead");
180                 return ERRORS;
181             }
182         }
183             
184         if (className == null)
185             throw new IllegalArgumentException JavaDoc("Test class name not specified");
186         
187         JUnitTest t= new JUnitTest(className);
188
189         // Add/overlay system properties on the properties from the Ant project
190
Hashtable JavaDoc p= System.getProperties();
191         for (Enumeration JavaDoc _enum = p.keys(); _enum.hasMoreElements(); ) {
192             Object JavaDoc key = _enum.nextElement();
193             props.put(key, p.get(key));
194         }
195         t.setProperties(props);
196     
197         EclipseTestRunner runner= new EclipseTestRunner(t, testPluginName, haltError, haltFail);
198         transferFormatters(runner);
199         runner.run();
200         return runner.getRetCode();
201     }
202
203     /**
204      *
205      */

206     public EclipseTestRunner(JUnitTest test, String JavaDoc testPluginName, boolean haltOnError, boolean haltOnFailure) {
207         fJunitTest= test;
208         fTestPluginName= testPluginName;
209         fHaltOnError= haltOnError;
210         fHaltOnFailure= haltOnFailure;
211         
212         try {
213             fSuite= getTest(test.getName());
214         } catch(Exception JavaDoc e) {
215             fRetCode = ERRORS;
216             fException = e;
217         }
218     }
219     
220     /**
221      * Returns the Test corresponding to the given suite.
222      */

223     protected Test getTest(String JavaDoc suiteClassName) throws TestFailedException {
224         if (suiteClassName.length() <= 0) {
225             clearStatus();
226             return null;
227         }
228         Class JavaDoc testClass= null;
229         try {
230             testClass= loadSuiteClass(suiteClassName);
231         } catch (ClassNotFoundException JavaDoc e) {
232             String JavaDoc clazz= e.getMessage();
233             if (clazz == null)
234                 clazz= suiteClassName;
235             runFailed("Class not found \""+clazz+"\"");
236             return null;
237         } catch(Exception JavaDoc e) {
238             runFailed("Error: "+e.toString());
239             return null;
240         }
241         Method JavaDoc suiteMethod= null;
242         try {
243             suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class JavaDoc[0]);
244         } catch(Exception JavaDoc e) {
245             // try to extract a test suite automatically
246
clearStatus();
247             return new TestSuite(testClass);
248         }
249         Test test= null;
250         try {
251             test= (Test)suiteMethod.invoke(null, new Class JavaDoc[0]); // static method
252
if (test == null)
253                 return test;
254         }
255         catch (InvocationTargetException JavaDoc e) {
256             runFailed("Failed to invoke suite():" + e.getTargetException().toString());
257             return null;
258         }
259         catch (IllegalAccessException JavaDoc e) {
260             runFailed("Failed to invoke suite():" + e.toString());
261             return null;
262         }
263         clearStatus();
264         return test;
265     }
266
267     protected void runFailed(String JavaDoc message) throws TestFailedException {
268         System.err.println(message);
269         throw new TestFailedException(message);
270     }
271
272     protected void clearStatus() {
273     }
274
275     /**
276      * Loads the class either with the system class loader or a
277      * plugin clsas loader if a plugin name was specified
278      */

279     protected Class JavaDoc loadSuiteClass(String JavaDoc suiteClassName) throws ClassNotFoundException JavaDoc {
280         if (fTestPluginName == null)
281             return Class.forName(suiteClassName);
282         Class JavaDoc loader= Platform.getBundle(fTestPluginName).loadClass(suiteClassName);
283         return loader;
284     }
285     
286     public void run() {
287 // IPerformanceMonitor pm = PerfMsrCorePlugin.getPerformanceMonitor(true);
288

289         fTestResult= new TestResult();
290         fTestResult.addListener(this);
291         for (int i= 0; i < formatters.size(); i++) {
292             fTestResult.addListener((TestListener)formatters.elementAt(i));
293         }
294
295         long start= System.currentTimeMillis();
296         fireStartTestSuite();
297         
298         if (fException != null) { // had an exception in the constructor
299
for (int i= 0; i < formatters.size(); i++) {
300                 ((TestListener)formatters.elementAt(i)).addError(null, fException);
301             }
302             fJunitTest.setCounts(1, 0, 1);
303             fJunitTest.setRunTime(0);
304         } else {
305             ByteArrayOutputStream JavaDoc errStrm = new ByteArrayOutputStream JavaDoc();
306             fSystemError= new PrintStream JavaDoc(errStrm);
307             
308             ByteArrayOutputStream JavaDoc outStrm = new ByteArrayOutputStream JavaDoc();
309             fSystemOut= new PrintStream JavaDoc(outStrm);
310
311             try {
312 // pm.snapshot(1); // before
313
fSuite.run(fTestResult);
314             } finally {
315  // pm.snapshot(2); // after
316
fSystemError.close();
317                 fSystemError= null;
318                 fSystemOut.close();
319                 fSystemOut= null;
320                 sendOutAndErr(new String JavaDoc(outStrm.toByteArray()), new String JavaDoc(errStrm.toByteArray()));
321                 fJunitTest.setCounts(fTestResult.runCount(), fTestResult.failureCount(), fTestResult.errorCount());
322                 fJunitTest.setRunTime(System.currentTimeMillis() - start);
323             }
324         }
325         fireEndTestSuite();
326
327         if (fRetCode != SUCCESS || fTestResult.errorCount() != 0) {
328             fRetCode = ERRORS;
329         } else if (fTestResult.failureCount() != 0) {
330             fRetCode = FAILURES;
331         }
332         
333 // pm.upload(getClass().getName());
334
}
335     
336     /**
337      * Returns what System.exit() would return in the standalone version.
338      *
339      * @return 2 if errors occurred, 1 if tests failed else 0.
340      */

341     public int getRetCode() {
342         return fRetCode;
343     }
344
345     /*
346      * @see TestListener.addFailure
347      */

348     public void startTest(Test t) {}
349
350     /*
351      * @see TestListener.addFailure
352      */

353     public void endTest(Test test) {}
354
355     /*
356      * @see TestListener.addFailure
357      */

358     public void addFailure(Test test, AssertionFailedError t) {
359         if (fHaltOnFailure) {
360             fTestResult.stop();
361         }
362     }
363
364     /*
365      * @see TestListener.addError
366      */

367     public void addError(Test test, Throwable JavaDoc t) {
368         if (fHaltOnError) {
369             fTestResult.stop();
370         }
371     }
372     
373     private void fireStartTestSuite() {
374         for (int i= 0; i < formatters.size(); i++) {
375             ((JUnitResultFormatter)formatters.elementAt(i)).startTestSuite(fJunitTest);
376         }
377     }
378
379     private void fireEndTestSuite() {
380         for (int i= 0; i < formatters.size(); i++) {
381             ((JUnitResultFormatter)formatters.elementAt(i)).endTestSuite(fJunitTest);
382         }
383     }
384
385     public void addFormatter(JUnitResultFormatter f) {
386         formatters.addElement(f);
387     }
388
389     /**
390      * Line format is: formatter=<classname>(,<pathname>)?
391      */

392     private static void createAndStoreFormatter(String JavaDoc line) throws BuildException {
393         FormatterElement fe = new FormatterElement();
394         String JavaDoc formatterClassName= null;
395         File JavaDoc formatterFile= null;
396         
397         int pos = line.indexOf(',');
398         if (pos == -1) {
399             formatterClassName= line;
400         } else {
401             formatterClassName= line.substring(0, pos);
402             formatterFile= new File JavaDoc(line.substring(pos + 1)); // the method is package visible
403
}
404         fgFromCmdLine.addElement(createFormatter(formatterClassName, formatterFile));
405     }
406
407     private static void transferFormatters(EclipseTestRunner runner) {
408         for (int i= 0; i < fgFromCmdLine.size(); i++) {
409             runner.addFormatter((JUnitResultFormatter)fgFromCmdLine.elementAt(i));
410         }
411     }
412
413     /*
414      * DUPLICATED from FormatterElement, since it is package visible only
415      */

416     private static JUnitResultFormatter createFormatter(String JavaDoc classname, File JavaDoc outfile) throws BuildException {
417         OutputStream JavaDoc out= System.out;
418
419         if (classname == null) {
420             throw new BuildException("you must specify type or classname");
421         }
422         Class JavaDoc f = null;
423         try {
424             f= EclipseTestRunner.class.getClassLoader().loadClass(classname);
425         } catch (ClassNotFoundException JavaDoc e) {
426             throw new BuildException(e);
427         }
428
429         Object JavaDoc o = null;
430         try {
431             o = f.newInstance();
432         } catch (InstantiationException JavaDoc e) {
433             throw new BuildException(e);
434         } catch (IllegalAccessException JavaDoc e) {
435             throw new BuildException(e);
436         }
437
438         if (!(o instanceof JUnitResultFormatter)) {
439             throw new BuildException(classname+" is not a JUnitResultFormatter");
440         }
441
442         JUnitResultFormatter r = (JUnitResultFormatter) o;
443
444         if (outfile != null) {
445             try {
446                 out = new FileOutputStream JavaDoc(outfile);
447             } catch (java.io.IOException JavaDoc e) {
448                 throw new BuildException(e);
449             }
450         }
451         r.setOutput(out);
452         return r;
453     }
454
455     private void sendOutAndErr(String JavaDoc out, String JavaDoc err) {
456         for (int i=0; i<formatters.size(); i++) {
457             JUnitResultFormatter formatter =
458                 ((JUnitResultFormatter)formatters.elementAt(i));
459             
460             formatter.setSystemOutput(out);
461             formatter.setSystemError(err);
462         }
463     }
464     
465     protected void handleOutput(String JavaDoc line) {
466         if (fSystemOut != null) {
467             fSystemOut.println(line);
468         }
469     }
470     
471     protected void handleErrorOutput(String JavaDoc line) {
472         if (fSystemError != null) {
473             fSystemError.println(line);
474         }
475     }
476 }
477
Popular Tags