All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy