1 // Copyright (C) 2004 by Object Refinery Limited |
|
2 // Written by David Gilbert (david.gilbert@object-refinery.com) |
|
3 // Modified by Peter Barth (peda@jnode.org) |
|
4 |
|
5 // This file is part of Mauve Reporter. |
|
6 |
|
7 // Mauve Reporter is free software; you can redistribute it and/or modify |
|
8 // it under the terms of the GNU General Public License as published by |
|
9 // the Free Software Foundation; either version 2 of the License, or |
|
10 // (at your option) any later version. |
|
11 |
|
12 // Mauve Reporter is distributed in the hope that it will be useful, |
|
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
15 // GNU General Public License for more details. |
|
16 |
|
17 // You should have received a copy of the GNU General Public License |
|
18 // along with Mauve Reporter; if not, write to the Free Software |
|
19 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|
20 package gnu.testlet.runner; |
|
21 |
|
22 import java.io.BufferedOutputStream; |
|
23 import java.io.File; |
|
24 import java.io.FileOutputStream; |
|
25 import java.io.IOException; |
|
26 import java.io.OutputStream; |
|
27 import java.io.OutputStreamWriter; |
|
28 import java.io.PrintWriter; |
|
29 import java.io.Writer; |
|
30 import java.text.DateFormat; |
|
31 import java.util.Date; |
|
32 import java.util.Iterator; |
|
33 |
|
34 /** |
|
35 * Generates a collection of HTML files that summarise the results |
|
36 * of a Mauve run. This is a quick-and-dirty implementation!! |
|
37 */ |
|
38 public class HTMLGenerator { |
|
39 |
|
40 /** |
|
41 * Creates an HTML report in the specified directory. |
|
42 * |
|
43 * @param run the Mauve run results. |
|
44 * @param rootDirectory the root directory. |
|
45 */ |
|
46 public static void createReport(RunResult run, File rootDirectory) throws IOException { |
|
47 // write basic HTML with info about package |
|
48 File summaryFile = new File(rootDirectory, "index.html"); |
|
49 Writer out = new OutputStreamWriter(new FileOutputStream(summaryFile), "UTF-8"); |
|
50 PrintWriter writer = new PrintWriter(out); |
|
51 writer.println("<HTML>"); |
|
52 writer.println("<HEAD><TITLE>Mauve Run: " + run.getName() + "</TITLE>"); |
|
53 writer.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></HEAD>"); |
|
54 writer.println("<BODY>"); |
|
55 writer.println("<h1>Mauve Run</h1>"); |
|
56 writer.println("<h2>Summary:</h2>"); |
|
57 int checkCount = run.getCheckCount(); |
|
58 int passed = run.getCheckCount(true); |
|
59 int failed = checkCount - passed; |
|
60 writer.println("Run Date: " + DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date()) + "<br>"); |
|
61 writer.println("Passed: " + passed + "<br>"); |
|
62 writer.println("Failed: " + failed + "<p>"); |
|
63 |
|
64 writer.println("<h2>Environment:</h2>"); |
|
65 |
|
66 writer.println("<table BORDER=\"0\" CELLPADDING=\"0\">"); |
|
67 writer.println("<tr>"); |
|
68 writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">"); |
|
69 writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">"); |
|
70 writer.println("<tr>"); |
|
71 writer.println("<td bgcolor=\"lightGray\">Property:</td>"); |
|
72 writer.println("<td bgcolor=\"lightGray\">Value:</td>"); |
|
73 writer.println("</tr>"); |
|
74 |
|
75 String[] propertyNames = run.getSystemPropertyNames(); |
|
76 for (int i = 0; i < propertyNames.length; i++) { |
|
77 String name = propertyNames[i]; |
|
78 writePropertyRow(name, run.getSystemProperty(name), writer); |
|
79 } |
|
80 |
|
81 writer.println("</table>"); |
|
82 writer.println("</td>"); |
|
83 writer.println("</tr>"); |
|
84 writer.println("</table><p>"); |
|
85 |
|
86 writer.println("<h2>Results:</h2>"); |
|
87 |
|
88 writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">"); |
|
89 writer.println("<tr>"); |
|
90 writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">"); |
|
91 writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">"); |
|
92 writer.println("<tr>"); |
|
93 writer.println("<td bgcolor=\"lightGray\">Package:</td>"); |
|
94 writer.println("<td bgcolor=\"lightGray\">Passed:</td>"); |
|
95 writer.println("<td bgcolor=\"lightGray\">Failed:</td>"); |
|
96 writer.println("<td bgcolor=\"lightGray\">Total:</td>"); |
|
97 writer.println("</tr>"); |
|
98 |
|
99 // loop through tests writing test results |
|
100 String top = null; |
|
101 Iterator iterator = run.getPackageIterator(); |
|
102 while (iterator.hasNext()) { |
|
103 PackageResult packageResult = (PackageResult) iterator.next(); |
|
104 String packageName = packageResult.getName().replace('.', '/'); |
|
105 String name; |
|
106 System.out.println("Generating " + packageName); |
|
107 if(top != null && packageName.startsWith(top)) |
|
108 name = " + "+ packageName.substring(top.length()+1); |
|
109 else { |
|
110 top = packageName; |
|
111 name = packageName; |
|
112 } |
|
113 // (1) write the summary line for the class HTML file |
|
114 writer.println("<tr>"); |
|
115 writer.println("<td bgcolor=\"white\"><a href=\"" + packageName + "/package_index.html\"" + ">" + name + "</a></td>"); |
|
116 writer.println("<td bgcolor=\"white\">" + packageResult.getCheckCount(true) + "</td>"); |
|
117 writer.println("<td bgcolor=\"white\">" + packageResult.getCheckCount(false) + "</td>"); |
|
118 writer.println("<td bgcolor=\"white\">" + packageResult.getCheckCount() + "</td>"); |
|
119 writer.println("</tr>"); |
|
120 // (2) generate an HTML page for the test and subfiles |
|
121 // for the tests |
|
122 try { |
|
123 HTMLGenerator.createPackageReport(packageResult, rootDirectory); |
|
124 } catch (Exception e) { |
|
125 String temp = packageResult.getName().replace('.', '/'); |
|
126 System.err.println("Couldn't create package report for " + temp); |
|
127 File tempDir = new File(rootDirectory, packageName); |
|
128 tempDir.mkdirs(); |
|
129 File tempFile = new File(tempDir, "package_index.html"); |
|
130 tempFile.createNewFile(); |
|
131 } |
|
132 } |
|
133 writer.println("</table>"); |
|
134 writer.println("</td>"); |
|
135 writer.println("</tr>"); |
|
136 writer.println("</table>"); |
|
137 writer.println("<p>"); |
|
138 Iterator missing = run.getMissingTestsIterator(); |
|
139 Iterator failures = run.getFaultyTestsIterator(); |
|
140 if(missing.hasNext() || failures.hasNext()) { |
|
141 writer.println("<h2>Unrunnable tests:</h2>"); |
|
142 |
|
143 writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">"); |
|
144 writer.println("<tr>"); |
|
145 writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">"); |
|
146 writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">"); |
|
147 writer.println("<tr>"); |
|
148 writer.println("<td bgcolor=\"lightGray\">name:</td>"); |
|
149 writer.println("<td bgcolor=\"lightGray\">problem:</td>"); |
|
150 writer.println("</tr>"); |
|
151 while(missing.hasNext()) |
|
152 writer.println("<tr><td bgcolor=\"white\">"+ (String) missing.next()+ |
|
153 "</td><td bgcolor=\"white\">Class not found</td></tr>"); |
|
154 while(failures.hasNext()) { |
|
155 String[] fail = (String[]) failures.next(); |
|
156 writer.println("<tr><td bgcolor=\"white\">"+ fail[0] +"</td><td bgcolor=\"white\">"+ |
|
157 fail[1] +"</td></tr>"); |
|
158 } |
|
159 writer.println("</table>"); |
|
160 writer.println("</td>"); |
|
161 writer.println("</tr>"); |
|
162 writer.println("</table>"); |
|
163 } |
|
164 |
|
165 writer.println("</BODY>"); |
|
166 writer.println("</HTML>"); |
|
167 writer.close(); |
|
168 } |
|
169 |
|
170 /** |
|
171 * Writes a row in a table for a pair of strings. |
|
172 * |
|
173 * @param property the property key. |
|
174 * @param value the property value. |
|
175 * @param writer the output stream. |
|
176 */ |
|
177 private static void writePropertyRow(String property, String value, PrintWriter writer) { |
|
178 writer.println("<tr>"); |
|
179 writer.println("<td bgcolor=\"white\">" + property + "</td>"); |
|
180 writer.println("<td bgcolor=\"white\">" + value + "</td>"); |
|
181 writer.println("</tr>"); |
|
182 } |
|
183 |
|
184 /** |
|
185 * Returns the number of directory levels in the specified package name. |
|
186 * |
|
187 * @param name the name. |
|
188 * |
|
189 * @return The number of directory levels. |
|
190 */ |
|
191 private static int countLevels(String name) { |
|
192 int result = 1; |
|
193 for (int i = 0; i < name.length(); i++) { |
|
194 if (name.charAt(i) == '/') result++; |
|
195 } |
|
196 return result; |
|
197 } |
|
198 |
|
199 /** |
|
200 * Creates an HTML page that summaries a package, and processes all the classes within |
|
201 * the package. |
|
202 * |
|
203 * @param packageResult the package result. |
|
204 * @param rootDirectory the root directory. |
|
205 */ |
|
206 public static void createPackageReport(PackageResult packageResult, File rootDirectory) throws IOException { |
|
207 // create directory for package |
|
208 String packageName = packageResult.getName().replace('.', '/'); |
|
209 String prefix = ""; |
|
210 int levels = countLevels(packageName); |
|
211 for (int i = 0; i < levels; i++) |
|
212 prefix += "../"; |
|
213 File packageDirectory = new File(rootDirectory, packageName); |
|
214 packageDirectory.mkdirs(); |
|
215 |
|
216 // write basic HTML with info about package |
|
217 File summaryFile = new File(packageDirectory, "package_index.html"); |
|
218 OutputStream out = new BufferedOutputStream(new FileOutputStream(summaryFile)); |
|
219 PrintWriter writer = new PrintWriter(out); |
|
220 writer.println("<HTML>"); |
|
221 writer.println("<HEAD><TITLE>Package Summary: " + packageResult.getName() + "</TITLE></HEAD>"); |
|
222 writer.println("<BODY>"); |
|
223 writer.println("<h2>Package: " + packageResult.getName() + "</h2>"); |
|
224 writer.println("<a href=\"" + prefix + "index.html\">Summary page</a><p>"); |
|
225 int checkCount = packageResult.getCheckCount(); |
|
226 int passed = packageResult.getCheckCount(true); |
|
227 int failed = checkCount - passed; |
|
228 writer.println("Passed: " + passed + "<br>"); |
|
229 writer.println("Failed: " + failed + "<p>"); |
|
230 writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">"); |
|
231 writer.println("<tr>"); |
|
232 writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">"); |
|
233 writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">"); |
|
234 writer.println("<tr>"); |
|
235 writer.println("<td bgcolor=\"lightGray\">Class:</td>"); |
|
236 writer.println("<td bgcolor=\"lightGray\">Passed:</td>"); |
|
237 writer.println("<td bgcolor=\"lightGray\">Failed:</td>"); |
|
238 writer.println("<td bgcolor=\"lightGray\">Total:</td>"); |
|
239 writer.println("</tr>"); |
|
240 |
|
241 // loop through tests writing test results |
|
242 Iterator iterator = packageResult.getClassIterator(); |
|
243 while (iterator.hasNext()) { |
|
244 ClassResult classResult = (ClassResult) iterator.next(); |
|
245 // (1) write the summary line for the class HTML file |
|
246 writer.println("<tr>"); |
|
247 writer.println("<td bgcolor=\"white\"><a href=\"" + classResult.getName() + "/class_index.html\"" + ">" + classResult.getName() + "</a></td>"); |
|
248 writer.println("<td bgcolor=\"white\">" + classResult.getCheckCount(true) + "</td>"); |
|
249 writer.println("<td bgcolor=\"white\">" + classResult.getCheckCount(false) + "</td>"); |
|
250 writer.println("<td bgcolor=\"white\">" + classResult.getCheckCount() + "</td>"); |
|
251 writer.println("</tr>"); |
|
252 // (2) generate an HTML page for the test and subfiles |
|
253 // for the tests |
|
254 HTMLGenerator.createClassReport(classResult, packageResult.getName(), packageDirectory); |
|
255 } |
|
256 // close the class file |
|
257 writer.println("</table>"); |
|
258 writer.println("</td>"); |
|
259 writer.println("</tr>"); |
|
260 writer.println("</table>"); |
|
261 writer.println("</BODY>"); |
|
262 writer.println("</HTML>"); |
|
263 writer.close(); |
|
264 } |
|
265 |
|
266 /** |
|
267 * Creates an HTML page summarising the results for a class, and processes all the tests for |
|
268 * the class. |
|
269 * |
|
270 * @param classResult the class results. |
|
271 * @param packageName the package name. |
|
272 * @param packageDirectory the package directory. |
|
273 */ |
|
274 public static void createClassReport(ClassResult classResult, String packageName, File packageDirectory) throws IOException { |
|
275 // create directory for class |
|
276 File classDirectory = new File(packageDirectory, classResult.getName()); |
|
277 classDirectory.mkdirs(); |
|
278 |
|
279 // write basic HTML with info about class |
|
280 File testFile = new File(classDirectory, "class_index.html"); |
|
281 OutputStream out = new BufferedOutputStream(new FileOutputStream(testFile)); |
|
282 PrintWriter writer = new PrintWriter(out); |
|
283 writer.println("<HTML>"); |
|
284 writer.println("<HEAD><TITLE>Class Summary: " + packageName + "." + classResult.getName() + "</TITLE></HEAD>"); |
|
285 writer.println("<BODY>"); |
|
286 writer.println("<h2>Class: " + "<a href=\"../package_index.html\">" + packageName +"</a>." + classResult.getName() + "</h2>"); |
|
287 int checkCount = classResult.getCheckCount(); |
|
288 int passed = classResult.getCheckCount(true); |
|
289 int failed = checkCount - passed; |
|
290 writer.println("Passed: " + passed + "<br>"); |
|
291 writer.println("Failed: " + failed + "<p>"); |
|
292 writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">"); |
|
293 writer.println("<tr>"); |
|
294 writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">"); |
|
295 writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">"); |
|
296 writer.println("<tr>"); |
|
297 writer.println("<td bgcolor=\"lightGray\">Test:</td>"); |
|
298 writer.println("<td bgcolor=\"lightGray\">Passed:</td>"); |
|
299 writer.println("<td bgcolor=\"lightGray\">Failed:</td>"); |
|
300 writer.println("<td bgcolor=\"lightGray\">Total:</td>"); |
|
301 writer.println("</tr>"); |
|
302 |
|
303 // loop through tests writing test results |
|
304 Iterator iterator = classResult.getTestIterator(); |
|
305 while (iterator.hasNext()) { |
|
306 TestResult testResult = (TestResult) iterator.next(); |
|
307 // (1) write the summary line for the class HTML file |
|
308 writer.println("<tr>"); |
|
309 writer.println("<td bgcolor=\"white\"><a href=\"" + testResult.getName() + ".html\"" + ">" + testResult.getName() + "</a></td>"); |
|
310 writer.println("<td bgcolor=\"white\">" + testResult.getCheckCount(true) + "</td>"); |
|
311 writer.println("<td bgcolor=\"white\">" + testResult.getCheckCount(false) + "</td>"); |
|
312 writer.println("<td bgcolor=\"white\">" + testResult.getCheckCount() + "</td>"); |
|
313 writer.println("</tr>"); |
|
314 // (2) generate an HTML page for the test and subfiles |
|
315 // for the tests |
|
316 HTMLGenerator.createTestReport(testResult, classResult.getName(), classDirectory); |
|
317 } |
|
318 // close the class file |
|
319 writer.println("</table>"); |
|
320 writer.println("</td>"); |
|
321 writer.println("</tr>"); |
|
322 writer.println("</table>"); |
|
323 writer.println("</BODY>"); |
|
324 writer.println("</HTML>"); |
|
325 writer.close(); |
|
326 } |
|
327 |
|
328 /** |
|
329 * Creates an HTML page that summarises a test. |
|
330 * |
|
331 * @param testResult the test result. |
|
332 * @param className the class name. |
|
333 * @param classDirectory the class directory. |
|
334 */ |
|
335 public static void createTestReport(TestResult testResult, String className, File classDirectory) throws IOException { |
|
336 |
|
337 // write basic HTML for test |
|
338 File testFile = new File(classDirectory, testResult.getName() + ".html"); |
|
339 Writer out = new OutputStreamWriter(new FileOutputStream(testFile), "UTF-8"); |
|
340 PrintWriter writer = new PrintWriter(out); |
|
341 writer.println("<HTML>"); |
|
342 writer.println("<HEAD><TITLE>Test Summary: " + className + "." + testResult.getName() + "</TITLE>\n"); |
|
343 writer.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></HEAD>"); |
|
344 writer.println("<BODY>"); |
|
345 writer.println("<h2>Test: <a href=\"class_index.html\">" + className + "</a>." + testResult.getName() + "</h2>"); |
|
346 int checkCount = testResult.getCheckCount(); |
|
347 int passed = testResult.getCheckCount(true); |
|
348 int failed = checkCount - passed; |
|
349 writer.println("Passed: " + passed + "<br>"); |
|
350 writer.println("Failed: " + failed + "<p>"); |
|
351 writer.println("<table BORDER=\"0\" width=\"100%\" CELLPADDING=\"0\">"); |
|
352 writer.println("<tr>"); |
|
353 writer.println("<td bgcolor=\"black\" VALIGN=\"TOP\">"); |
|
354 writer.println("<table BORDER=\"0\" WIDTH=\"100%\" CELLSPACING=\"1\" CELLPADDING=\"3\">"); |
|
355 writer.println("<tr>"); |
|
356 writer.println("<td bgcolor=\"lightGray\">Check Number:</td>"); |
|
357 writer.println("<td bgcolor=\"lightGray\">Check Point:</td>"); |
|
358 writer.println("<td bgcolor=\"lightGray\">Passed?:</td>"); |
|
359 writer.println("<td bgcolor=\"lightGray\">Expected:</td>"); |
|
360 writer.println("<td bgcolor=\"lightGray\">Actual:</td>"); |
|
361 writer.println("</tr>"); |
|
362 |
|
363 // loop through checks adding a summary line for each check |
|
364 Iterator iterator = testResult.getCheckIterator(); |
|
365 while (iterator.hasNext()) { |
|
366 CheckResult check = (CheckResult) iterator.next(); |
|
367 // write a summary line (ID, pass/fail, actual, expected); |
|
368 writer.println("<tr><td bgcolor=\"white\">" + check.getNumber() + |
|
369 "</td><td bgcolor=\"white\">" + check.getCheckPoint() + |
|
370 "</td><td bgcolor=\"" + (check.getPassed() ? "white" : "red") + "\">" + |
|
371 check.getPassed() + "</td><td bgcolor=\"white\">" + check.getExpected() + |
|
372 "</td><td bgcolor=\"white\">" + check.getActual() + "</td>"); |
|
373 if (!check.getPassed()) { |
|
374 try { |
|
375 createLogReport(check, className, testResult.getName(), classDirectory); |
|
376 } catch (Exception e) { |
|
377 System.err.println("Couldn't write report for class " + className); |
|
378 File temp = new File(classDirectory, testResult.getName() + "_log.html"); |
|
379 temp.createNewFile(); |
|
380 } |
|
381 } |
|
382 writer.println("</td>"); |
|
383 writer.println("</tr>"); |
|
384 } |
|
385 writer.println("</table>"); |
|
386 writer.println("</td>"); |
|
387 writer.println("</tr>"); |
|
388 writer.println("</table>"); |
|
389 if(testResult.isFailed()) { |
|
390 writer.println("<h2>Run aborted due to exception</h2>"); |
|
391 writer.println("<pre>"+ testResult.getFailedMessage() +"</pre>"); |
|
392 } |
|
393 writer.println("</BODY>"); |
|
394 writer.println("</HTML>"); |
|
395 writer.close(); |
|
396 } |
|
397 |
|
398 /** |
|
399 * Creates an HTML page that summarises the log for a check. |
|
400 * |
|
401 * @param checkResult the test result. |
|
402 * @param className the class name. |
|
403 * @param testName the test name. |
|
404 * @param classDirectory the class directory. |
|
405 */ |
|
406 public static void createLogReport(CheckResult checkResult, String className, String testName, File classDirectory) throws IOException { |
|
407 // write basic HTML for test |
|
408 File logFile = new File(classDirectory, testName + "_log.html"); |
|
409 OutputStream out = new BufferedOutputStream(new FileOutputStream(logFile)); |
|
410 PrintWriter writer = new PrintWriter(out); |
|
411 writer.println("<HTML>"); |
|
412 writer.println("<HEAD><TITLE>Log: " + testName + "</TITLE>"); |
|
413 writer.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></HEAD>"); |
|
414 writer.println("<BODY>"); |
|
415 writer.println(checkResult.getLog()); |
|
416 writer.println("</BODY>"); |
|
417 writer.println("</HTML>"); |
|
418 writer.close(); |
|
419 } |
|
420 } |
|