J
Jacob
As HTML report generation from JUnit supprisingly appears to be an Ant
feature only (refer to an earlier post on this subject), I supply my
home brewed version of this as promised (my appologize for the long
listing
Some of the code is based on ideas from junit-addons as documented in
the source. Writing a custom report is probably not done by the book
due to the very poor documentation and strange (and quite fat) API of
JUnit.
Disclaimer: It was written in a rush and can probably be improved in a
number of ways.
Usage:
java HtmlTestReport /my/path/to/classes > test-report.html
Jacob
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import junit.framework.Test;
import junit.framework.TestSuite;
import junit.framework.TestResult;
import junit.framework.TestFailure;
import junit.framework.AssertionFailedError;
import junit.framework.TestListener;
/**
* Class for creating a HTML JUnit test report.
*
* @author <a href="mailto:[email protected]">Jacob Dreyer</a>
*/
public final class HtmlTestReport implements TestListener
{
/** Background color of header */
private final String HEADER_COLOR = "\"#ccccff\"";
/** Background color of report */
private final String BACKGROUND_COLOR = "\"#ffffff\"";
/** Background color of successful tests */
private final String SUCCESS_COLOR = "\"#99ff99\"";
/** Background color of failed tests */
private final String FAILURE_COLOR = "\"#ff9999\"";
/** Directory of source root */
private final File sourceDirectory_;
/** Directory of classes root */
private final File classDirectory_;
/** Overall start time for report generation */
private long time0_;
/** Start time for current test */
private long startTime_;
/** Error message of current test */
private StringBuffer message_;
/** Total number of succeeding tests */
private int nSuccess_ = 0;
/** Total number of failed tests */
private int nFailed_ = 0;
/**
* Create a HTML report instance. Typical usage:
* <pre>
* File sourceDir = new File("/home/joe/dev/src");
* File classDir = new File("/home/joe/dev/classes");
*
* HtmlTestReport report = new HtmlTestReport(sourceDir, classDir);
* report.print();
* </pre>
* The HTML report is written to stdout and will typically be
* redirected to a .html file.
*
* @param sourceDirectory Root directory of source. If specified, it
* will be used to create a link to the source
* file of failing classes. May be null.
* @param classDirectory Root directory of classes.
*/
public HtmlTestReport(File sourceDirectory, File classDirectory)
{
assert classDirectory != null : "Illegal class directory";
sourceDirectory_ = sourceDirectory;
classDirectory_ = classDirectory;
time0_ = System.currentTimeMillis();
}
/**
* Print the HTML report to standard out.
*/
public void print()
{
try {
// Extract the test suite
TestSuite suite = HtmlTestReport.build(classDirectory_);
// Print report header
printHeader();
// Loop through all the tests and make the report run the test
// and capture the result
for (int i = 0; i < suite.testCount(); i++) {
Test test = suite.testAt(i);
run(test);
}
// Print report footer
printFooter();
}
catch (IOException exception) {
exception.printStackTrace();
}
}
/**
* Convert the specified number of milliseconds into a readable
* string in the form [nSeconds].[nMilliseconds]
*
* @param nMillis Number of milliseconds to convert.
* @return String representation of the input.
*/
private static String getTime(long nMillis)
{
assert nMillis >= 0 : "Illegal time specification";
long nSeconds = nMillis / 1000;
nMillis -= nSeconds * 1000;
StringBuffer time = new StringBuffer();
time.append(nSeconds);
time.append('.');
if (nMillis < 100) time.append('0');
if (nMillis < 10) time.append('0');
time.append(nMillis);
return time.toString();
}
/**
* Print the HTML report header.
*/
private void printHeader()
{
System.out.println("<html>");
System.out.println("<table" +
" cellpadding=\"5\"" +
" cellspacing=\"0\"" +
" bgcolor=" + BACKGROUND_COLOR +
" border=\"1\"" +
" width=\"100%\"" +
">");
System.out.println(" <tr>");
System.out.println(" <td bgcolor=" + HEADER_COLOR + " colspan=2>" +
"<font size=+2>" +
"<b>Test</b>" +
"</font>" +
"</td>");
System.out.println(" <td bgcolor=" + HEADER_COLOR + ">" +
"<font size=+2>" +
"<b>Time</b>" +
"</font>" +
"</td>");
System.out.println(" <td align=\"right\" bgcolor=" + HEADER_COLOR + ">" +
"<font size=+2>" +
"<b>" + new Date() + "</b>" +
"</font>" +
"</td>");
System.out.println(" </tr>");
}
/**
* Print the HTML report footer.
*/
private void printFooter()
{
int nTotal = nSuccess_ + nFailed_;
String color = nFailed_ == 0 ? SUCCESS_COLOR : FAILURE_COLOR;
System.out.println(" <tr>");
System.out.println(" <td colspan=3> </td>");
System.out.println(" <td bgcolor=" + color + ">");
System.out.println(" <table border=0 cellspacing=0 cellpadding=0>");
System.out.println(" <tr>");
System.out.println(" <td><font size=+0 face=\"helvetica\"><b>Failed</b></font></td>");
System.out.println(" <td><font size=+0 face=\"courier\">" +
nFailed_ +
" (" + (double) nFailed_ / nTotal * 100.0 + "%)" +
"</font>" +
"</td>");
System.out.println(" </tr>");
System.out.println(" <tr>");
System.out.println(" <td><font size=+0 face=\"helvetica\"><b>Success </b></font></td>");
System.out.println(" <td><font size=+0 face=\"courier\">" +
nSuccess_ +
" (" + (double) nSuccess_ / nTotal * 100.0 + "%)" +
"</font>" +
"</td>");
System.out.println(" </tr>");
System.out.println(" <tr>");
System.out.println(" <td><font size=+0 face=\"helvetica\"><b>Total</b></font></td>");
System.out.println(" <td><font size=+0 face=\"courier\">" +
nTotal +
"</font>" +
"</td>");
System.out.println(" </tr>");
System.out.println(" <tr>");
System.out.println(" <td><font size=+0 face=\"helvetica\"><b>Time</b></font></td>");
System.out.println(" <td><font size=+0 face=\"courier\">" +
HtmlTestReport.getTime(System.currentTimeMillis() - time0_) +
"</td>");
System.out.println(" </tr>");
System.out.println(" </table>");
System.out.println(" </td>");
System.out.println(" </tr>");
System.out.println("</table>");
System.out.println("</html>");
}
/**
* Run the specified test and capture the result in the report.
*
* @param test Test to run.
*/
private void run(Test test)
{
System.out.println(" <tr>");
System.out.println(" <td colspan=4>" +
"<font face=\"courier\">" +
"<b>" + test.toString() + "</b>" +
"</font>" +
"</td>");
System.out.println(" </tr>");
TestResult result = new TestResult();
result.addListener(this);
test.run(result);
}
/**
* Create an anchor tag from the specified class and file name.
*
* @param className Fully specified class name of class to link to.
* @param fileName File where the class resides.
* @param lineNo Line number to scroll to (TODO: not currently used).
* @return Anchor string of the form "<a href='link'>file</a>".
*/
private String toLink(String className, String fileName, int lineNo)
{
assert sourceDirectory_ != null : "Source not available";
assert className != null : "Missing class name";
assert fileName != null : "Missing file name";
assert lineNo >= 0 : "Illegal line number spcifier";
String base = sourceDirectory_.toString() + "/";
String packageName = className.substring(0, className.lastIndexOf('.'));
String link = "<a href=\"" +
base +
packageName.replace(".", "/") +
"/" +
fileName +
"\">" +
fileName + ":" + lineNo +
"</a>";
return link;
}
/**
* Add the appropriate report content for a starting test.
* This method is called by JUnit when a test is about to start.
*
* @param test Test that is about to start.
*/
public void startTest(Test test)
{
assert test != null : "Test cannot be null";
startTime_ = System.currentTimeMillis();
message_ = new StringBuffer();
String name = test.toString();
String testName = name.substring(0, name.indexOf('('));
System.out.println(" <tr>");
System.out.println(" <td> </td>");
System.out.println(" <td valign=\"top\"><font face=\"courier\"><b>" + testName +
"</b></font></td>");
}
/**
* Add the appropriate report content for a failed test.
* This method is called by JUnit when a test fails.
*
* @param test Test that is failing.
* @param throwable Throwable indicating the failure
*/
public void addError(Test test, Throwable throwable)
{
assert test != null : "Test cannot be null";
assert throwable != null : "Exception must be specified for failing test";
StackTraceElement stackTrace[] = throwable.getStackTrace();
for (int i = 0; i < stackTrace.length; i++) {
String className = stackTrace.getClassName();
if (!className.startsWith("junit")) {
message_.append(stackTrace.getClassName());
message_.append(" ");
if (sourceDirectory_ != null)
message_.append(toLink(stackTrace.getClassName(),
stackTrace.getFileName(),
stackTrace.getLineNumber()));
message_.append("<br>");
break;
}
}
message_.append(" " + throwable.getMessage());
}
/**
* Add the appropriate report content for a failed test.
* This method is called by JUnit when a test fails.
*
* @param test Test that is failing.
* @param throwable Throwable indicating the failure
*/
public void addFailure(Test test, AssertionFailedError error)
{
assert test != null : "Test cannot be null";
assert error != null : "Exception must be specified for failing test";
// Treat failures and errors the same
addError(test, error);
}
/**
* Add the appropriate report content for the end of a test.
* This method is called by JUnit when a test is done.
*
* @param test Test that is done.
*/
public void endTest(Test test)
{
assert test != null : "Test cannot be null";
// Compute the test duration
long time = System.currentTimeMillis() - startTime_;
System.out.println(" <td valign=\"top\"><font face=\"courier\"> " +
HtmlTestReport.getTime(time) +
"</font></td>");
// Test was a success
if (message_.length() == 0) {
nSuccess_++;
System.out.println(" <td bgcolor=" + SUCCESS_COLOR +
"<font face=\"helvetica\"><b>Success</b></font></td>");
}
// Test failed
else {
nFailed_++;
System.out.println(" <td bgcolor=" + FAILURE_COLOR + ">" +
message_.toString() +
"</td>");
}
System.out.println(" </tr>");
}
/**
* Method for creating a test suite from all tests
* found in the present directory and its sub directories.
*
* @param directory Root directory for test search.
* @return Test suite compund of all tests found.
*/
private static TestSuite build(File directory)
throws IOException
{
assert directory != null : "Directory cannot be null";
TestSuite suite = new TestSuite(directory.getName());
// Get list of all classes in the path
List<String> classNames = HtmlTestReport.getAllClasses(directory);
for (String className : classNames) {
try {
Class clazz = Class.forName(className);
// Filter out all non-test classes
if (junit.framework.TestCase.class.isAssignableFrom(clazz)) {
// Because a 'suite' method doesn't always exist in a TestCase,
// we need to use the try/catch so that tests can also be
// automatically extracted
try {
Method suiteMethod = clazz.getMethod("suite", new Class[0]);
Test test = (Test) suiteMethod.invoke(null);
suite.addTest(test);
}
catch (NoSuchMethodException exception) {
suite.addTest(new TestSuite(clazz));
}
catch (IllegalAccessException exception) {
exception.printStackTrace();
// Ignore
}
catch (InvocationTargetException exception) {
exception.printStackTrace();
// Ignore
}
}
}
catch (ClassNotFoundException exception) {
// Ignore
}
}
return suite;
}
/**
* Retrieve all classes from the specified path.
*
* @param root Root of directory of where to search for classes.
* @return List of classes on the form "com.company.ClassName".
*/
private static List<String> getAllClasses(File root)
throws IOException
{
assert root != null : "Root cannot be null";
// Prepare the return array
List<String> classNames = new ArrayList<String>();
// Get all classes recursively
String path = root.getCanonicalPath();
HtmlTestReport.getAllClasses(root, path.length() + 1, classNames);
return classNames;
}
/**
* Retrive all classes from the specified path.
*
* @param root Root of directory of where to search for classes.
* @param prefixLength Index into root path name of path considered.
* @param result Array to add classes found
*/
private static void getAllClasses(File root, int prefixLength,
List<String> result)
throws IOException
{
assert root != null : "Root cannot be null";
assert prefixLength >= 0 : "Illegal index specifier";
assert result != null : "Missing return array";
// Scan all entries in the directory
for (File entry : root.listFiles()) {
// If the entry is a directory, get classes recursively
if (entry.isDirectory()) {
if (entry.canRead())
getAllClasses(entry, prefixLength, result);
}
// Entry is a file. Filter out non-classes and inner classes
else {
String path = entry.getPath();
boolean isClass = path.endsWith(".class") && path.indexOf("$") < 0;
if (isClass) {
String name = entry.getCanonicalPath().substring(prefixLength);
String className = name.replace(File.separatorChar, '.').
substring(0, name.length() - 6);
result.add(className);
}
}
}
}
/**
* A JUnit HTML report generator. Typical usage:
* <pre>
* java HtmlTestReport /home/joe/dev/classes > test.html
* </pre>
*
* @param arguments Comand line arguments.
*/
public static void main(String[] arguments)
{
// Parse command line arguments
if (arguments.length < 1 || arguments.length > 2) {
System.err.println("Usage: HtmlTestReport classDir [sourceDir]");
}
File classDirectory = new File(arguments[0]);
File sourceDirectory = null;
if (arguments.length == 2)
sourceDirectory = new File(arguments[1]);
// Create a HTML report instance
HtmlTestReport report = new HtmlTestReport(sourceDirectory,
classDirectory);
// Print report to standard out
report.print();
}
}
feature only (refer to an earlier post on this subject), I supply my
home brewed version of this as promised (my appologize for the long
listing
Some of the code is based on ideas from junit-addons as documented in
the source. Writing a custom report is probably not done by the book
due to the very poor documentation and strange (and quite fat) API of
JUnit.
Disclaimer: It was written in a rush and can probably be improved in a
number of ways.
Usage:
java HtmlTestReport /my/path/to/classes > test-report.html
Jacob
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import junit.framework.Test;
import junit.framework.TestSuite;
import junit.framework.TestResult;
import junit.framework.TestFailure;
import junit.framework.AssertionFailedError;
import junit.framework.TestListener;
/**
* Class for creating a HTML JUnit test report.
*
* @author <a href="mailto:[email protected]">Jacob Dreyer</a>
*/
public final class HtmlTestReport implements TestListener
{
/** Background color of header */
private final String HEADER_COLOR = "\"#ccccff\"";
/** Background color of report */
private final String BACKGROUND_COLOR = "\"#ffffff\"";
/** Background color of successful tests */
private final String SUCCESS_COLOR = "\"#99ff99\"";
/** Background color of failed tests */
private final String FAILURE_COLOR = "\"#ff9999\"";
/** Directory of source root */
private final File sourceDirectory_;
/** Directory of classes root */
private final File classDirectory_;
/** Overall start time for report generation */
private long time0_;
/** Start time for current test */
private long startTime_;
/** Error message of current test */
private StringBuffer message_;
/** Total number of succeeding tests */
private int nSuccess_ = 0;
/** Total number of failed tests */
private int nFailed_ = 0;
/**
* Create a HTML report instance. Typical usage:
* <pre>
* File sourceDir = new File("/home/joe/dev/src");
* File classDir = new File("/home/joe/dev/classes");
*
* HtmlTestReport report = new HtmlTestReport(sourceDir, classDir);
* report.print();
* </pre>
* The HTML report is written to stdout and will typically be
* redirected to a .html file.
*
* @param sourceDirectory Root directory of source. If specified, it
* will be used to create a link to the source
* file of failing classes. May be null.
* @param classDirectory Root directory of classes.
*/
public HtmlTestReport(File sourceDirectory, File classDirectory)
{
assert classDirectory != null : "Illegal class directory";
sourceDirectory_ = sourceDirectory;
classDirectory_ = classDirectory;
time0_ = System.currentTimeMillis();
}
/**
* Print the HTML report to standard out.
*/
public void print()
{
try {
// Extract the test suite
TestSuite suite = HtmlTestReport.build(classDirectory_);
// Print report header
printHeader();
// Loop through all the tests and make the report run the test
// and capture the result
for (int i = 0; i < suite.testCount(); i++) {
Test test = suite.testAt(i);
run(test);
}
// Print report footer
printFooter();
}
catch (IOException exception) {
exception.printStackTrace();
}
}
/**
* Convert the specified number of milliseconds into a readable
* string in the form [nSeconds].[nMilliseconds]
*
* @param nMillis Number of milliseconds to convert.
* @return String representation of the input.
*/
private static String getTime(long nMillis)
{
assert nMillis >= 0 : "Illegal time specification";
long nSeconds = nMillis / 1000;
nMillis -= nSeconds * 1000;
StringBuffer time = new StringBuffer();
time.append(nSeconds);
time.append('.');
if (nMillis < 100) time.append('0');
if (nMillis < 10) time.append('0');
time.append(nMillis);
return time.toString();
}
/**
* Print the HTML report header.
*/
private void printHeader()
{
System.out.println("<html>");
System.out.println("<table" +
" cellpadding=\"5\"" +
" cellspacing=\"0\"" +
" bgcolor=" + BACKGROUND_COLOR +
" border=\"1\"" +
" width=\"100%\"" +
">");
System.out.println(" <tr>");
System.out.println(" <td bgcolor=" + HEADER_COLOR + " colspan=2>" +
"<font size=+2>" +
"<b>Test</b>" +
"</font>" +
"</td>");
System.out.println(" <td bgcolor=" + HEADER_COLOR + ">" +
"<font size=+2>" +
"<b>Time</b>" +
"</font>" +
"</td>");
System.out.println(" <td align=\"right\" bgcolor=" + HEADER_COLOR + ">" +
"<font size=+2>" +
"<b>" + new Date() + "</b>" +
"</font>" +
"</td>");
System.out.println(" </tr>");
}
/**
* Print the HTML report footer.
*/
private void printFooter()
{
int nTotal = nSuccess_ + nFailed_;
String color = nFailed_ == 0 ? SUCCESS_COLOR : FAILURE_COLOR;
System.out.println(" <tr>");
System.out.println(" <td colspan=3> </td>");
System.out.println(" <td bgcolor=" + color + ">");
System.out.println(" <table border=0 cellspacing=0 cellpadding=0>");
System.out.println(" <tr>");
System.out.println(" <td><font size=+0 face=\"helvetica\"><b>Failed</b></font></td>");
System.out.println(" <td><font size=+0 face=\"courier\">" +
nFailed_ +
" (" + (double) nFailed_ / nTotal * 100.0 + "%)" +
"</font>" +
"</td>");
System.out.println(" </tr>");
System.out.println(" <tr>");
System.out.println(" <td><font size=+0 face=\"helvetica\"><b>Success </b></font></td>");
System.out.println(" <td><font size=+0 face=\"courier\">" +
nSuccess_ +
" (" + (double) nSuccess_ / nTotal * 100.0 + "%)" +
"</font>" +
"</td>");
System.out.println(" </tr>");
System.out.println(" <tr>");
System.out.println(" <td><font size=+0 face=\"helvetica\"><b>Total</b></font></td>");
System.out.println(" <td><font size=+0 face=\"courier\">" +
nTotal +
"</font>" +
"</td>");
System.out.println(" </tr>");
System.out.println(" <tr>");
System.out.println(" <td><font size=+0 face=\"helvetica\"><b>Time</b></font></td>");
System.out.println(" <td><font size=+0 face=\"courier\">" +
HtmlTestReport.getTime(System.currentTimeMillis() - time0_) +
"</td>");
System.out.println(" </tr>");
System.out.println(" </table>");
System.out.println(" </td>");
System.out.println(" </tr>");
System.out.println("</table>");
System.out.println("</html>");
}
/**
* Run the specified test and capture the result in the report.
*
* @param test Test to run.
*/
private void run(Test test)
{
System.out.println(" <tr>");
System.out.println(" <td colspan=4>" +
"<font face=\"courier\">" +
"<b>" + test.toString() + "</b>" +
"</font>" +
"</td>");
System.out.println(" </tr>");
TestResult result = new TestResult();
result.addListener(this);
test.run(result);
}
/**
* Create an anchor tag from the specified class and file name.
*
* @param className Fully specified class name of class to link to.
* @param fileName File where the class resides.
* @param lineNo Line number to scroll to (TODO: not currently used).
* @return Anchor string of the form "<a href='link'>file</a>".
*/
private String toLink(String className, String fileName, int lineNo)
{
assert sourceDirectory_ != null : "Source not available";
assert className != null : "Missing class name";
assert fileName != null : "Missing file name";
assert lineNo >= 0 : "Illegal line number spcifier";
String base = sourceDirectory_.toString() + "/";
String packageName = className.substring(0, className.lastIndexOf('.'));
String link = "<a href=\"" +
base +
packageName.replace(".", "/") +
"/" +
fileName +
"\">" +
fileName + ":" + lineNo +
"</a>";
return link;
}
/**
* Add the appropriate report content for a starting test.
* This method is called by JUnit when a test is about to start.
*
* @param test Test that is about to start.
*/
public void startTest(Test test)
{
assert test != null : "Test cannot be null";
startTime_ = System.currentTimeMillis();
message_ = new StringBuffer();
String name = test.toString();
String testName = name.substring(0, name.indexOf('('));
System.out.println(" <tr>");
System.out.println(" <td> </td>");
System.out.println(" <td valign=\"top\"><font face=\"courier\"><b>" + testName +
"</b></font></td>");
}
/**
* Add the appropriate report content for a failed test.
* This method is called by JUnit when a test fails.
*
* @param test Test that is failing.
* @param throwable Throwable indicating the failure
*/
public void addError(Test test, Throwable throwable)
{
assert test != null : "Test cannot be null";
assert throwable != null : "Exception must be specified for failing test";
StackTraceElement stackTrace[] = throwable.getStackTrace();
for (int i = 0; i < stackTrace.length; i++) {
String className = stackTrace.getClassName();
if (!className.startsWith("junit")) {
message_.append(stackTrace.getClassName());
message_.append(" ");
if (sourceDirectory_ != null)
message_.append(toLink(stackTrace.getClassName(),
stackTrace.getFileName(),
stackTrace.getLineNumber()));
message_.append("<br>");
break;
}
}
message_.append(" " + throwable.getMessage());
}
/**
* Add the appropriate report content for a failed test.
* This method is called by JUnit when a test fails.
*
* @param test Test that is failing.
* @param throwable Throwable indicating the failure
*/
public void addFailure(Test test, AssertionFailedError error)
{
assert test != null : "Test cannot be null";
assert error != null : "Exception must be specified for failing test";
// Treat failures and errors the same
addError(test, error);
}
/**
* Add the appropriate report content for the end of a test.
* This method is called by JUnit when a test is done.
*
* @param test Test that is done.
*/
public void endTest(Test test)
{
assert test != null : "Test cannot be null";
// Compute the test duration
long time = System.currentTimeMillis() - startTime_;
System.out.println(" <td valign=\"top\"><font face=\"courier\"> " +
HtmlTestReport.getTime(time) +
"</font></td>");
// Test was a success
if (message_.length() == 0) {
nSuccess_++;
System.out.println(" <td bgcolor=" + SUCCESS_COLOR +
"<font face=\"helvetica\"><b>Success</b></font></td>");
}
// Test failed
else {
nFailed_++;
System.out.println(" <td bgcolor=" + FAILURE_COLOR + ">" +
message_.toString() +
"</td>");
}
System.out.println(" </tr>");
}
/**
* Method for creating a test suite from all tests
* found in the present directory and its sub directories.
*
* @param directory Root directory for test search.
* @return Test suite compund of all tests found.
*/
private static TestSuite build(File directory)
throws IOException
{
assert directory != null : "Directory cannot be null";
TestSuite suite = new TestSuite(directory.getName());
// Get list of all classes in the path
List<String> classNames = HtmlTestReport.getAllClasses(directory);
for (String className : classNames) {
try {
Class clazz = Class.forName(className);
// Filter out all non-test classes
if (junit.framework.TestCase.class.isAssignableFrom(clazz)) {
// Because a 'suite' method doesn't always exist in a TestCase,
// we need to use the try/catch so that tests can also be
// automatically extracted
try {
Method suiteMethod = clazz.getMethod("suite", new Class[0]);
Test test = (Test) suiteMethod.invoke(null);
suite.addTest(test);
}
catch (NoSuchMethodException exception) {
suite.addTest(new TestSuite(clazz));
}
catch (IllegalAccessException exception) {
exception.printStackTrace();
// Ignore
}
catch (InvocationTargetException exception) {
exception.printStackTrace();
// Ignore
}
}
}
catch (ClassNotFoundException exception) {
// Ignore
}
}
return suite;
}
/**
* Retrieve all classes from the specified path.
*
* @param root Root of directory of where to search for classes.
* @return List of classes on the form "com.company.ClassName".
*/
private static List<String> getAllClasses(File root)
throws IOException
{
assert root != null : "Root cannot be null";
// Prepare the return array
List<String> classNames = new ArrayList<String>();
// Get all classes recursively
String path = root.getCanonicalPath();
HtmlTestReport.getAllClasses(root, path.length() + 1, classNames);
return classNames;
}
/**
* Retrive all classes from the specified path.
*
* @param root Root of directory of where to search for classes.
* @param prefixLength Index into root path name of path considered.
* @param result Array to add classes found
*/
private static void getAllClasses(File root, int prefixLength,
List<String> result)
throws IOException
{
assert root != null : "Root cannot be null";
assert prefixLength >= 0 : "Illegal index specifier";
assert result != null : "Missing return array";
// Scan all entries in the directory
for (File entry : root.listFiles()) {
// If the entry is a directory, get classes recursively
if (entry.isDirectory()) {
if (entry.canRead())
getAllClasses(entry, prefixLength, result);
}
// Entry is a file. Filter out non-classes and inner classes
else {
String path = entry.getPath();
boolean isClass = path.endsWith(".class") && path.indexOf("$") < 0;
if (isClass) {
String name = entry.getCanonicalPath().substring(prefixLength);
String className = name.replace(File.separatorChar, '.').
substring(0, name.length() - 6);
result.add(className);
}
}
}
}
/**
* A JUnit HTML report generator. Typical usage:
* <pre>
* java HtmlTestReport /home/joe/dev/classes > test.html
* </pre>
*
* @param arguments Comand line arguments.
*/
public static void main(String[] arguments)
{
// Parse command line arguments
if (arguments.length < 1 || arguments.length > 2) {
System.err.println("Usage: HtmlTestReport classDir [sourceDir]");
}
File classDirectory = new File(arguments[0]);
File sourceDirectory = null;
if (arguments.length == 2)
sourceDirectory = new File(arguments[1]);
// Create a HTML report instance
HtmlTestReport report = new HtmlTestReport(sourceDirectory,
classDirectory);
// Print report to standard out
report.print();
}
}