/* | |
* Copyright 2000-2004 The Apache Software Foundation | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
* | |
*/ | |
package tools.JUnit; | |
import java.io.*; | |
import java.text.NumberFormat; | |
import java.util.*; | |
import junit.framework.AssertionFailedError; | |
import junit.framework.Test; | |
import org.apache.tools.ant.BuildException; | |
import org.apache.tools.ant.taskdefs.optional.junit.*; | |
/** | |
* Prints plain text output of the test to a specified Writer. | |
* | |
* @author Stefan Bodewig | |
*/ | |
public class SimpleResultFormatter implements JUnitResultFormatter { | |
public static int TEST_SUCCESS = 0; | |
public static int TEST_FAILURE = 1; | |
public static int TEST_ERROR = 2; | |
public static int TEST_UNKNOWN = 3; | |
// Lets capture STDOUT and STDERR | |
ByteArrayOutputStream bOut = new ByteArrayOutputStream(); | |
ByteArrayOutputStream bErr = new ByteArrayOutputStream(); | |
PrintStream _out; | |
PrintStream _err; | |
private TestRecord testRecord; | |
Collection records; | |
/** | |
* Formatter for timings. | |
*/ | |
private NumberFormat nf = NumberFormat.getInstance(); | |
/** | |
* Timing helper. | |
*/ | |
private Hashtable testStarts = new Hashtable(); | |
/** | |
* Where to write the log to. | |
*/ | |
private OutputStream out; | |
/** | |
* Helper to store intermediate output. | |
*/ | |
private StringWriter inner; | |
/** | |
* Convenience layer on top of {@link #inner inner}. | |
*/ | |
private PrintWriter wri; | |
/** | |
* Suppress endTest if testcase failed. | |
*/ | |
private Hashtable failed = new Hashtable(); | |
private String systemOutput = null; | |
private String systemError = null; | |
public SimpleResultFormatter() { | |
inner = new StringWriter(); | |
wri = new PrintWriter(inner); | |
} | |
public void setOutput(OutputStream out) { | |
this.out = out; | |
} | |
public void setSystemOutput(String out) { | |
// We will be capturing Stdout and Stderr internally so this is | |
// redundant | |
//systemOutput = out; | |
} | |
public void setSystemError(String err) { | |
// We will be capturing Stdout and Stderr internally so this is | |
// redundant | |
//systemError = err; | |
} | |
/** | |
* Signals starting of a Suite of tests | |
*/ | |
public void startTestSuite(JUnitTest suite) { | |
records = new ArrayList(); | |
} | |
/** | |
* The whole testsuite ended. | |
*/ | |
public void endTestSuite(JUnitTest suite) throws BuildException { | |
String newLine = System.getProperty("line.separator"); | |
StringBuffer sb = new StringBuffer("Testsuite: "); | |
sb.append(suite.getName()); | |
sb.append(newLine); | |
sb.append("Tests run: "); | |
sb.append(suite.runCount()); | |
sb.append(", Failures: "); | |
sb.append(suite.failureCount()); | |
sb.append(", Errors: "); | |
sb.append(suite.errorCount()); | |
sb.append(", Time elapsed: "); | |
sb.append(nf.format(suite.getRunTime() / 1000.0)); | |
sb.append(" sec"); | |
sb.append(newLine); | |
//sb.append("DEBUG: " + records.size()); | |
sb.append("======================================================"); | |
Iterator it = records.iterator(); | |
while (it.hasNext()) | |
{ | |
TestRecord rec = (TestRecord) it.next(); | |
sb.append(newLine); | |
sb.append("Test: " + rec.getTestname()).append(newLine); | |
sb.append("Result: " + rec.getStatusString()).append(newLine); | |
float diff = rec.getEndTime() - rec.getStartTime(); | |
sb.append("Start time: " + rec.getStartTime()).append(newLine); | |
sb.append("End time : " + rec.getEndTime()).append(newLine); | |
sb.append("Execution time: " + diff/1000).append(newLine); | |
sb.append("[STDOUT]").append(newLine); | |
sb.append(rec.getSysout()).append(newLine); | |
sb.append("[STDERR]").append(newLine); | |
sb.append(rec.getSyserr()).append(newLine); | |
if (rec.isFailure()) | |
{ | |
sb.append("[EXCEPTION]").append(newLine); | |
sb.append(JUnitTestRunner.getFilteredTrace(rec.getThrowable())); | |
sb.append(newLine); | |
} | |
sb.append("======================================================"); | |
} | |
/* | |
// append the err and output streams to the log | |
if (systemOutput != null && systemOutput.length() > 0) { | |
sb.append("------------- Standard Output ---------------") | |
.append(newLine) | |
.append(systemOutput) | |
.append("------------- ---------------- ---------------") | |
.append(newLine); | |
} | |
if (systemError != null && systemError.length() > 0) { | |
sb.append("------------- Standard Error -----------------") | |
.append(newLine) | |
.append(systemError) | |
.append("------------- ---------------- ---------------") | |
.append(newLine); | |
} | |
sb.append(newLine); | |
*/ | |
if (out != null) { | |
try { | |
out.write(sb.toString().getBytes()); | |
wri.close(); | |
//out.write(inner.toString().getBytes()); | |
out.flush(); | |
} catch (IOException ioex) { | |
throw new BuildException("Unable to write output", ioex); | |
} finally { | |
if (out != System.out && out != System.err) { | |
try { | |
out.close(); | |
} catch (IOException e) { | |
// ignore | |
} | |
} | |
} | |
} | |
} | |
/** | |
* Interface TestListener. | |
* | |
* <p>A new Test is started. | |
*/ | |
public void startTest(Test t) { | |
// Lets start the capture | |
System.out.flush(); | |
System.err.flush(); | |
_out = System.out; | |
_err = System.err; | |
bOut.reset(); | |
bErr.reset(); | |
System.setOut(new PrintStream(bOut)); | |
System.setErr(new PrintStream(bErr)); | |
// Store the previous record | |
testRecord = new TestRecord(t.toString()); | |
testRecord.setStartTime(System.currentTimeMillis()); | |
testStarts.put(t, new Long(System.currentTimeMillis())); | |
failed.put(t, Boolean.FALSE); | |
} | |
/** | |
* Interface TestListener. | |
* | |
* <p>A Test is finished. | |
*/ | |
public void endTest(Test test) { | |
long endTime = System.currentTimeMillis(); | |
System.out.flush(); | |
System.err.flush(); | |
// Update the test record | |
testRecord.setSysout(bOut.toString()); | |
testRecord.setSyserr(bErr.toString()); | |
testRecord.setEndTime(endTime); | |
// If the test did not fail, record it as a success | |
if (!testRecord.isFailure()) | |
testRecord.setStatus(TEST_SUCCESS); | |
// Add it to the set | |
records.add(testRecord); | |
System.setOut(_out); | |
System.setErr(_err); | |
} | |
/** | |
* Interface TestListener for JUnit > 3.4. | |
* | |
* <p>A Test failed. | |
*/ | |
public void addFailure(Test test, AssertionFailedError t) { | |
//addFailure(test, (Throwable) t); | |
testRecord.setStatus(TEST_FAILURE); | |
testRecord.setThrowable(t); | |
// Record end time now.. | |
} | |
/** | |
* Interface TestListener. | |
* | |
* <p>An error occured while running the test. | |
*/ | |
public void addError(Test test, Throwable t) { | |
testRecord.setStatus(TEST_ERROR); | |
testRecord.setThrowable(t); | |
} | |
/** | |
* Utility class to record per test data like test name, status, start | |
* and end time, STDOUT, STDERR from text execution etc. | |
*/ | |
private class TestRecord | |
{ | |
public TestRecord(String name) | |
{ | |
setTestname(name); | |
} | |
private String testname; | |
private String sysout; | |
private String syserr; | |
private Throwable t; | |
private long startTime; | |
private long endTime; | |
private int status; | |
boolean failed = false; | |
private String testUnitName; | |
private String testLogicalName; | |
public void setTestname(String name) | |
{ | |
this.testname = name; | |
} | |
public String getTestname() | |
{ | |
return testname; | |
} | |
public void setStatus(int status) | |
{ | |
this.status = status; | |
if (status == TEST_ERROR || status == TEST_FAILURE) | |
failed = true; | |
} | |
public int getStatus() | |
{ | |
return status; | |
} | |
public String getStatusString() | |
{ | |
return (status == TEST_SUCCESS)?"SUCCESS": | |
(status == TEST_ERROR)?"ERROR":"FAILURE"; | |
} | |
public boolean isFailure() | |
{ | |
return failed; | |
} | |
public String getSysout() | |
{ | |
return sysout; | |
} | |
public void setSysout(String sysout) | |
{ | |
this.sysout = sysout; | |
} | |
public String getSyserr() | |
{ | |
return syserr; | |
} | |
public void setSyserr(String syserr) | |
{ | |
this.syserr = syserr; | |
} | |
public Throwable getThrowable() | |
{ | |
return t; | |
} | |
public void setThrowable(Throwable t) | |
{ | |
this.t = t; | |
} | |
public long getStartTime() | |
{ | |
return startTime; | |
} | |
public void setStartTime(long startTime) | |
{ | |
this.startTime = startTime; | |
} | |
public long getEndTime() | |
{ | |
return endTime; | |
} | |
public void setEndTime(long endTime) | |
{ | |
this.endTime = endTime; | |
} | |
} | |
} // PlainJUnitResultFormatter |