water.junit.XMLTestReporter Maven / Gradle / Ivy
The newest version!
package water.junit;
import org.apache.commons.lang.StringEscapeUtils;
import org.junit.Ignore;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import water.H2ORuntime;
import water.TestUtil;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
/**
* Simple XML reporter.
*
* BY default outputing XML reports into build/test-results folder.
* Can be changed via '-Djunit.reports.dir' JVM property.
*
* Adapted from https://www.redhat.com/archives/pki-devel/2011-December/msg00001.html
*
*/
@Ignore("Support for tests, but no actual tests here")
public class XMLTestReporter extends RunListener {
DateFormat dateFormat;
DocumentBuilderFactory docBuilderFactory;
DocumentBuilder docBuilder;
Document document;
TransformerFactory transFactory;
Transformer trans;
String reportsDir;
Element testSuiteElement;
long testSuiteStartTime;
Element testCaseElement;
long testCaseStartTime;
String currentTestSuiteName;
long testCount;
long successCount;
long failureCount;
PrintStream stdOut;
PrintStream stdErr;
ByteArrayOutputStream out;
ByteArrayOutputStream err;
public XMLTestReporter() throws Exception {
dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
docBuilderFactory = DocumentBuilderFactory.newInstance();
docBuilder = docBuilderFactory.newDocumentBuilder();
document = docBuilder.newDocument();
testCaseElement = document.createElement("testcase");
transFactory = TransformerFactory.newInstance();
trans = transFactory.newTransformer();
trans.setOutputProperty(OutputKeys.INDENT, "yes");
reportsDir = System.getProperty("junit.reports.dir", "build/test-results");
File rdir = new File(reportsDir);
if (rdir.isFile()) throw new IllegalArgumentException(reportsDir + " is not a directory!");
if (!rdir.exists()) rdir.mkdirs();
}
@Override
public void testRunFinished(Result result) throws Exception {
if (currentTestSuiteName != null) {
finishTestSuite(); // finish last suite
}
}
@Override
public void testStarted(Description description) throws Exception {
final String testSuiteName = makeTestSuiteName(description);
if (currentTestSuiteName == null) {
startTestSuite(testSuiteName); // start first suite
} else if (!currentTestSuiteName.equals(testSuiteName)) {
finishTestSuite(); // finish old suite
startTestSuite(testSuiteName); // start new suite
}
currentTestSuiteName = testSuiteName;
startTestCase(description);
}
private String makeTestSuiteName(Description description) {
String clusterType = TestUtil.MINCLOUDSIZE > 1 ? "multi" : "single";
return clusterType + "." + description.getClassName();
}
@Override
public void testFinished(Description description) {
finishTestCase();
recordTestCaseSuccess();
}
@Override
public void testFailure(Failure failure) {
finishTestCase();
recordTestCaseFailure(failure);
}
private void startTestSuite(String testSuiteName) throws Exception {
testSuiteStartTime = System.currentTimeMillis();
document = docBuilder.newDocument();
// test suite
testSuiteElement = document.createElement("testsuite");
document.appendChild(testSuiteElement);
testSuiteElement.setAttribute("name", StringEscapeUtils.escapeXml(testSuiteName));
testSuiteElement.setAttribute("timestamp",
StringEscapeUtils.escapeXml(dateFormat.format(new Date(testSuiteStartTime))));
testSuiteElement.setAttribute("hostname",
StringEscapeUtils.escapeXml(InetAddress.getLocalHost().getHostName()));
testSuiteElement.setAttribute("ncpu",
StringEscapeUtils.escapeXml(Integer.toString(Runtime.getRuntime().availableProcessors())));
testSuiteElement.setAttribute("activecpu",
StringEscapeUtils.escapeXml(Integer.toString(H2ORuntime.availableProcessors())));
// system properties
Element propertiesElement = document.createElement("properties");
testSuiteElement.appendChild(propertiesElement);
for (String name : System.getProperties().stringPropertyNames()) {
Element propertyElement = document.createElement("property");
propertyElement.setAttribute("name", StringEscapeUtils.escapeXml(name));
propertyElement.setAttribute("value", StringEscapeUtils.escapeXml(System.getProperty(name)));
propertiesElement.appendChild(propertyElement);
}
// reset counters
testCount = 0;
successCount = 0;
failureCount = 0;
// redirect outputs
stdOut = System.out;
out = new ByteArrayOutputStream();
System.setOut(new PrintStream(new TeeOutputStream(out, stdOut), true));
stdErr = System.err;
err = new ByteArrayOutputStream();
System.setErr(new PrintStream(new TeeOutputStream(err, stdErr), true));
}
private void finishTestSuite() throws Exception {
double time = (System.currentTimeMillis() - testSuiteStartTime) / 1000.0;
testSuiteElement.setAttribute("time", "" + time);
// save counters
long errorCount = testCount - successCount - failureCount;
testSuiteElement.setAttribute("tests", "" + testCount);
testSuiteElement.setAttribute("failures", "" + failureCount);
testSuiteElement.setAttribute("errors", "" + errorCount);
// restore outputs
System.setOut(stdOut);
System.setErr(stdErr);
Element systemOutElement = document.createElement("system-out");
testSuiteElement.appendChild(systemOutElement);
systemOutElement.appendChild(
document.createCDATASection(out.toString())
);
Element systemErrElement = document.createElement("system-err");
testSuiteElement.appendChild(systemErrElement);
systemErrElement.appendChild(
document.createCDATASection(err.toString())
);
// write to file
FileWriter fw = new FileWriter(
reportsDir + File.separator + "TEST-" + currentTestSuiteName + ".xml"
);
StreamResult sr = new StreamResult(fw);
DOMSource source = new DOMSource(document);
trans.transform(source, sr);
fw.close();
}
private void startTestCase(Description description) {
testCaseStartTime = System.currentTimeMillis();
testCaseElement = document.createElement("testcase");
testSuiteElement.appendChild(testCaseElement);
testCaseElement.setAttribute("classname", description.getClassName());
testCaseElement.setAttribute("name", description.getMethodName());
testCount++;
}
private void finishTestCase() {
double time = (System.currentTimeMillis() - testCaseStartTime) / 1000.0;
testCaseElement.setAttribute("time", "" + time);
}
private void recordTestCaseSuccess() {
successCount++;
}
private void recordTestCaseFailure(Failure failure) {
Element failureElement = document.createElement("failure");
testCaseElement.appendChild(failureElement);
Description description = failure.getDescription();
String exceptionName = failure.getException().getClass().getName();
failureElement.setAttribute("message", failure.getMessage());
failureElement.setAttribute("type", exceptionName);
Text messageElement = document.createTextNode(
exceptionName + ": " +failure.getMessage() + "\n\tat " +
description.getClassName() + "." + description.getMethodName() + "()"
);
failureElement.appendChild(messageElement);
failureCount++;
}
}
/** Output stream which duplicate given input to given target streams.
*
* WARNING: do not close underlying streams! */
class TeeOutputStream extends OutputStream {
final private OutputStream[] targets;
public TeeOutputStream(OutputStream... targets) {
this.targets = targets;
}
@Override
public void write(int b) throws IOException {
for (OutputStream target : targets)
target.write(b);
}
@Override
public void flush() throws IOException {
for (OutputStream target : targets)
target.flush();
}
}