Package org.pluginbuilder.autotestsuite.junit4

Source Code of org.pluginbuilder.autotestsuite.junit4.XmlJUnit4Formatter

package org.pluginbuilder.autotestsuite.junit4;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.tools.ant.taskdefs.optional.junit.XMLConstants;
import org.apache.tools.ant.util.DateUtils;
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSException;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;

/**
* {@link JUnit4Formatter} that mimics the output of
* {@link org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter}.
*
* @author Markus Wiederkehr
*/
public class XmlJUnit4Formatter extends JUnit4Formatter implements XMLConstants {

  private static final boolean GENERATE_PROPERTIES = true;
  private static final String UNKNOWN = "unknown";

  private final File file;

  private final Map<Description, TestHelper> testHelpers = new HashMap<Description, TestHelper>();

  private Document doc;
  private Element rootElement;

  public XmlJUnit4Formatter(File file) {
    if (file == null)
      throw new IllegalArgumentException();

    this.file = file;
  }

  @Override
  public void testRunStarted(Description description) throws Exception {
    testHelpers.clear();

    doc = getDocumentBuilder().newDocument();
    rootElement = doc.createElement( TESTSUITE );
    doc.appendChild( rootElement );

    String name = description.getDisplayName();
    rootElement.setAttribute( ATTR_NAME, name == null ? UNKNOWN : name );

    final String timestamp = DateUtils.format( new Date(), DateUtils.ISO8601_DATETIME_PATTERN );
    rootElement.setAttribute( TIMESTAMP, timestamp );
    rootElement.setAttribute( HOSTNAME, getHostname() );

    Properties props = System.getProperties();

    if (GENERATE_PROPERTIES) {
      Element propsElement = doc.createElement( PROPERTIES );
      rootElement.appendChild( propsElement );

      for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements();) {
        String propName = (String) e.nextElement();
        Element propElement = doc.createElement( PROPERTY );
        propsElement.appendChild( propElement );
        propElement.setAttribute( ATTR_NAME, propName );
        propElement.setAttribute( ATTR_VALUE, props.getProperty( propName ) );
      }
    }
  }

  @Override
  public void testRunFinished(Result result) throws Exception {
    rootElement.setAttribute( ATTR_TESTS, "" + result.getRunCount() );
    rootElement.setAttribute( ATTR_FAILURES, "" + result.getFailureCount() );
    // JUnit 4 no longer seems to distinguish between failures and errors
    rootElement.setAttribute( ATTR_ERRORS, "" + 0 );
    rootElement.setAttribute( ATTR_TIME, "" + (result.getRunTime() / 1000.0) );
  }

  @Override
  public void testStarted(Description description) throws Exception {
    getTestHelper( description );
  }

  @Override
  public void testFailure(Failure failure) throws Exception {
    getTestHelper( failure.getDescription() ).testFailure( failure );
  }

  @Override
  public void testFinished(Description description) throws Exception {
    getTestHelper( description ).testFinished( rootElement );

    testHelpers.remove( description );
  }

  @Override
  public void setSystemOutput(String out) {
    formatOutput( SYSTEM_OUT, out );
  }

  @Override
  public void setSystemError(String err) {
    formatOutput( SYSTEM_ERR, err );
  }

  @Override
  public void save() throws IOException {
    write( doc, new FileOutputStream( file ), true );
  }

  private TestHelper getTestHelper(Description description) {
    TestHelper testHelper = testHelpers.get( description );
    if (testHelper == null) {
      testHelper = new TestHelper( doc, description );
      testHelpers.put( description, testHelper );
    }
    return testHelper;
  }

  private String getHostname() {
    try {
      return InetAddress.getLocalHost().getHostName();
    } catch (UnknownHostException e) {
      return "localhost";
    }
  }

  private void formatOutput(String type, String output) {
    Element outputElement = doc.createElement( type );
    rootElement.appendChild( outputElement );
    outputElement.appendChild( doc.createCDATASection( output ) );
  }

  private DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
    return DocumentBuilderFactory.newInstance().newDocumentBuilder();
  }

  private void write(Document doc, OutputStream out, boolean close) throws IOException {
    try {
      DOMImplementationLS ls = (DOMImplementationLS) doc.getImplementation().getFeature( "LS", "3.0" );
      LSSerializer serializer = ls.createLSSerializer();
      DOMConfiguration domConfig = serializer.getDomConfig();
      trySetPrettyPrint( domConfig );

      LSOutput lsOutput = ls.createLSOutput();
      lsOutput.setEncoding( "UTF-8" );
      lsOutput.setByteStream( out );

      try {
        serializer.write( doc, lsOutput );
      } catch (LSException e) {
        throw (IOException) new IOException( e.getMessage() ).initCause( e );
      }

      out.flush();
    } finally {
      if (close)
        out.close();
    }
  }

  private void trySetPrettyPrint(DOMConfiguration domConfig) {
    // Setting pretty-print works with Sun Java 6 but not Java 5
    try {
      domConfig.setParameter( "format-pretty-print", true );
    } catch (DOMException ignored) {
    }
  }

  private static final class TestHelper {
    private final Document doc;
    private final long timeStarted;
    private final Element testElement;

    public TestHelper(Document doc, Description description) {
      this.doc = doc;
      timeStarted = System.currentTimeMillis();
      testElement = doc.createElement( TESTCASE );

      testElement.setAttribute( ATTR_NAME, getTestName( description ) );
      testElement.setAttribute( ATTR_CLASSNAME, getTestClassName( description ) );
    }

    public void testFailure(Failure failure) {
      Element failureElement = doc.createElement( FAILURE );
      testElement.appendChild( failureElement );

      String message = failure.getMessage();
      if (message != null && message.length() > 0)
        failureElement.setAttribute( ATTR_MESSAGE, message );

      failureElement.setAttribute( ATTR_TYPE, failure.getException().getClass().getName() );

      String strace = failure.getTrace();
      Text trace = doc.createTextNode( strace );
      failureElement.appendChild( trace );
    }

    public void testFinished(Element rootElement) {
      long testDuration = System.currentTimeMillis() - timeStarted;
      testElement.setAttribute( ATTR_TIME, Double.toString( testDuration / 1000.0 ) );

      rootElement.appendChild( testElement );
    }

    private String getTestName(Description description) {
      String name = description.getDisplayName();
      int paren = name.lastIndexOf( '(' );
      if (paren != -1 && name.endsWith( ")" ))
        return name.substring( 0, paren );
      return name;
    }

    private String getTestClassName(Description description) {
      String name = description.getDisplayName();
      int paren = name.lastIndexOf( '(' );
      if (paren != -1 && name.endsWith( ")" ))
        return name.substring( paren + 1, name.length() - 1 );
      return UNKNOWN;
    }
  }

}
TOP

Related Classes of org.pluginbuilder.autotestsuite.junit4.XmlJUnit4Formatter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.