1 package junit.runner;
2
3 import junit.framework.*;
4 import java.lang.reflect.*;
5 import java.text.NumberFormat;
6 import java.io.*;
7 import java.util.*;
8
9 /**
10 * Base class for all test runners.
11 * This class was born live on stage in Sardinia during XP2000.
12 */
|
13 public abstract class BaseTestRunner implements TestListener {
|
14 public static final String SUITE_METHODNAME= "suite";
15
16 private static Properties fPreferences;
|
17 static int fgMaxMessageLength= 500;
18 static boolean fgFilterStack= true;
19 boolean fLoading= true;
|
20
21 /*
22 * Implementation of TestListener
23 */
24 public synchronized void startTest(Test test) {
|
25 > testStarted(test.toString());
26 > }
|
27
28 protected static void setPreferences(Properties preferences) {
|
29 > fPreferences= preferences;
30 > }
|
31
32 protected static Properties getPreferences() {
|
33 if (fPreferences == null) {
34 fPreferences= new Properties();
35 fPreferences.put("loading", "true");
36 fPreferences.put("filterstack", "true");
37 readPreferences();
|
38 }
|
39 return fPreferences;
|
40 }
41
42 public static void savePreferences() throws IOException {
|
43 > FileOutputStream fos= new FileOutputStream(getPreferencesFile());
|
44 try {
|
45 > getPreferences().store(fos, "");
46 > } finally {
47 > fos.close();
|
48 }
|
49 > }
|
50
51 public void setPreference(String key, String value) {
|
52 > getPreferences().setProperty(key, value);
53 > }
|
54
55 public synchronized void endTest(Test test) {
|
56 > testEnded(test.toString());
57 > }
|
58
59 public synchronized void addError(final Test test, final Throwable t) {
|
60 > testFailed(TestRunListener.STATUS_ERROR, test, t);
61 > }
|
62
63 public synchronized void addFailure(final Test test, final AssertionFailedError t) {
|
64 > testFailed(TestRunListener.STATUS_FAILURE, test, t);
65 > }
|
66
67 // TestRunListener implementation
68
69 public abstract void testStarted(String testName);
70
71 public abstract void testEnded(String testName);
72
73 public abstract void testFailed(int status, Test test, Throwable t);
74
75 /**
76 * Returns the Test corresponding to the given suite. This is
77 * a template method, subclasses override runFailed(), clearStatus().
78 */
79 public Test getTest(String suiteClassName) {
|
80 if (suiteClassName.length() <= 0) {
|
81 > clearStatus();
82 > return null;
|
83 }
|
84 Class testClass= null;
|
85 try {
|
86 testClass= loadSuiteClass(suiteClassName);
87 } catch (ClassNotFoundException e) {
|
88 > String clazz= e.getMessage();
89 > if (clazz == null)
90 > clazz= suiteClassName;
91 > runFailed("Class not found \""+clazz+"\"");
92 > return null;
|
93 } catch(Exception e) {
|
94 > runFailed("Error: "+e.toString());
95 > return null;
|
96 }
|
97 Method suiteMethod= null;
|
98 try {
|
99 suiteMethod= testClass.getMethod(SUITE_METHODNAME, new Class[0]);
100 } catch(Exception e) {
|
101 // try to extract a test suite automatically
|
102 > clearStatus();
103 > return new TestSuite(testClass);
|
104 }
|
105 if (! Modifier.isStatic(suiteMethod.getModifiers())) {
106 runFailed("Suite() method must be static");
107 return null;
|
108 }
|
109 Test test= null;
|
110 try {
|
111 test= (Test)suiteMethod.invoke(null, new Class[0]); // static method
112 if (test == null)
|
113 > return test;
|
114 }
|
115 catch (InvocationTargetException e) {
|
116 > runFailed("Failed to invoke suite():" + e.getTargetException().toString());
117 > return null;
|
118 }
119 catch (IllegalAccessException e) {
|
120 > runFailed("Failed to invoke suite():" + e.toString());
121 > return null;
|
122 }
123
|
124 clearStatus();
125 return test;
|
126 }
127
128 /**
129 * Returns the formatted string of the elapsed time.
130 */
131 public String elapsedTimeAsString(long runTime) {
|
132 > return NumberFormat.getInstance().format((double)runTime/1000);
|
133 }
134
135 /**
136 * Processes the command line arguments and
137 * returns the name of the suite class to run or null
138 */
139 protected String processArguments(String[] args) {
|
140 > String suiteName= null;
141 > for (int i= 0; i < args.length; i++) {
142 > if (args[i].equals("-noloading")) {
143 > setLoading(false);
144 > } else if (args[i].equals("-nofilterstack")) {
145 > fgFilterStack= false;
146 > } else if (args[i].equals("-c")) {
147 > if (args.length > i+1)
148 > suiteName= extractClassName(args[i+1]);
|
149 else
|
150 > System.out.println("Missing Test class name");
151 > i++;
|
152 } else {
|
153 > suiteName= args[i];
|
154 }
155 }
|
156 > return suiteName;
|
157 }
158
159 /**
160 * Sets the loading behaviour of the test runner
161 */
162 public void setLoading(boolean enable) {
|
163 > fLoading= enable;
164 > }
|
165 /**
166 * Extract the class name from a String in VA/Java style
167 */
168 public String extractClassName(String className) {
|
169 > if(className.startsWith("Default package for"))
170 > return className.substring(className.lastIndexOf(".")+1);
171 > return className;
|
172 }
173
174 /**
175 * Truncates a String to the maximum length.
176 */
177 public static String truncate(String s) {
|
178 > if (fgMaxMessageLength != -1 && s.length() > fgMaxMessageLength)
179 > s= s.substring(0, fgMaxMessageLength)+"...";
180 > return s;
|
181 }
182
183 /**
184 * Override to define how to handle a failed loading of
185 * a test suite.
186 */
187 protected abstract void runFailed(String message);
188
189 /**
190 * Returns the loaded Class for a suite name.
191 */
192 protected Class loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
|
193 return getLoader().load(suiteClassName);
|
194 }
195
196 /**
197 * Clears the status message.
198 */
199 protected void clearStatus() { // Belongs in the GUI TestRunner class
|
200 }
|
201
202 /**
203 * Returns the loader to be used.
204 */
205 public TestSuiteLoader getLoader() {
|
206 if (useReloadingTestSuiteLoader())
207 return new ReloadingTestSuiteLoader();
|
208 > return new StandardTestSuiteLoader();
|
209 }
210
211 protected boolean useReloadingTestSuiteLoader() {
|
212 return getPreference("loading").equals("true") && !inVAJava() && fLoading;
|
213 }
214
215 private static File getPreferencesFile() {
|
216 String home= System.getProperty("user.home");
217 return new File(home, "junit.properties");
|
218 }
219
220 private static void readPreferences() {
|
221 InputStream is= null;
|
222 try {
|
223 is= new FileInputStream(getPreferencesFile());
|
224 > setPreferences(new Properties(getPreferences()));
225 > getPreferences().load(is);
226 > } catch (IOException e) {
|
227 try {
228 if (is != null)
|
229 > is.close();
|
230 } catch (IOException e1) {
|
231 > }
|
232 }
233 }
|
234
235 public static String getPreference(String key) {
|
236 return getPreferences().getProperty(key);
|
237 }
238
239 public static int getPreference(String key, int dflt) {
|
240 String value= getPreference(key);
241 int intValue= dflt;
242 if (value == null)
243 return intValue;
|
244 try {
|
245 > intValue= Integer.parseInt(value);
246 > } catch (NumberFormatException ne) {
247 > }
248 > return intValue;
|
249 }
250
251 public static boolean inVAJava() {
252 try {
|
253 Class.forName("com.ibm.uvm.tools.DebugSupport");
|
254 > }
|
255 catch (Exception e) {
|
256 return false;
|
257 }
|
258 > return true;
|
259 }
260
261 /**
262 * Returns a filtered stack trace
263 */
264 public static String getFilteredTrace(Throwable t) {
|
265 > StringWriter stringWriter= new StringWriter();
266 > PrintWriter writer= new PrintWriter(stringWriter);
267 > t.printStackTrace(writer);
268 > StringBuffer buffer= stringWriter.getBuffer();
269 > String trace= buffer.toString();
270 > return BaseTestRunner.getFilteredTrace(trace);
|
271 }
272
273 /**
274 * Filters stack frames from internal JUnit classes
275 */
276 public static String getFilteredTrace(String stack) {
|
277 if (showStackRaw())
|
278 > return stack;
|
279
|
280 StringWriter sw= new StringWriter();
281 PrintWriter pw= new PrintWriter(sw);
282 StringReader sr= new StringReader(stack);
283 BufferedReader br= new BufferedReader(sr);
|
284
285 String line;
286 try {
|
287 while ((line= br.readLine()) != null) {
288 if (!filterLine(line))
289 pw.println(line);
|
290 }
|
291 } catch (Exception IOException) {
|
292 > return stack; // return the stack unfiltered
|
293 }
|
294 return sw.toString();
|
295 }
296
297 protected static boolean showStackRaw() {
|
298 return !getPreference("filterstack").equals("true") || fgFilterStack == false;
|
299 }
300
301 static boolean filterLine(String line) {
|
302 String[] patterns= new String[] {
|
303 "junit.framework.TestCase",
304 "junit.framework.TestResult",
305 "junit.framework.TestSuite",
306 "junit.framework.Assert.", // don't filter AssertionFailure
307 "junit.swingui.TestRunner",
308 "junit.awtui.TestRunner",
309 "junit.textui.TestRunner",
310 "java.lang.reflect.Method.invoke("
311 };
|
312 for (int i= 0; i < patterns.length; i++) {
313 if (line.indexOf(patterns[i]) > 0)
314 return true;
|
315 }
|
316 return false;
|
317 }
318
319 static {
|
320 fgMaxMessageLength= getPreference("maxmessage", fgMaxMessageLength);
321 }
|
322
323 } |