package nl.hsac.fitnesse.junit;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* JUnit RunListener so that build log is updated with progress info while tests run.
*/
public class ProgressLoggerListener extends RunListener {
private final PrintStream out;
private String currentTestClassName = null;
private SimpleDateFormat formatter;
private int totalChildCount;
private int currentChild;
public ProgressLoggerListener() {
this(System.out);
}
public ProgressLoggerListener(final PrintStream out) {
this.out = out;
this.currentTestClassName = null;
this.formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ");
this.totalChildCount = 0;
this.currentChild = 0;
}
@Override
public void testRunStarted(Description description) throws Exception {
super.testRunStarted(description);
totalChildCount = totalChildCount(description);
currentChild = 0;
report("testRun Started ('%s' tests)", totalChildCount);
}
private int totalChildCount(Description description) {
int count = 0;
if (description != null) {
count = description.testCount();
}
return count;
}
@Override
public void testStarted(Description description) throws Exception {
final String testClassName = getTestClassName(description);
final String testName = getTestName(description);
if (currentTestClassName == null || !currentTestClassName.equals(testClassName)) {
testRunFinished(null);
report("testSuite Started '%s'", testClassName);
currentTestClassName = testClassName;
}
if (testName == null
|| !(testName.endsWith(".SuiteSetUp")
|| testName.endsWith(".SuiteTearDown"))) {
// incrementing on setup/teardown causes current to become larger than total
// that looks strangs
currentChild++;
}
report("test Started '%s' (%s / %s)", testName, currentChild, totalChildCount);
}
@Override
public void testFinished(Description description) throws Exception {
final String testName = getTestName(description);
report("test Finished '%s'\n", testName);
}
@Override
public void testFailure(Failure failure) throws Exception {
String trace = "";
if (failure.getTrace() != null && !failure.getTrace().isEmpty()) {
trace = failure.getTrace();
}
report("test Failed '%s' message='%s' details='%s'",
getTestName(failure.getDescription()),
"failed",
trace);
testFinished(failure.getDescription());
}
@Override
public void testIgnored(Description description) throws Exception {
report("test Ignored '%s'", getTestName(description));
}
@Override
public void testRunFinished(Result result) throws Exception {
if (currentTestClassName != null) {
report("testSuite Finished '%s'\n\n", currentTestClassName);
}
}
protected void report(String pattern, Object... parameters) {
out.print(formatter.format(new Date()));
out.println(String.format(pattern, parameters));
}
/**
* @param description JUnit description of test executed
* @return name to use in report
*/
protected String getTestName(Description description) {
return description.getMethodName();
}
protected String getTestClassName(final Description description) {
return description.getTestClass().getName();
}
public void setFormatter(SimpleDateFormat formatter) {
this.formatter = formatter;
}
}