/** * 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. * * Copyright 2012-2015 the original author or authors. */ package org.assertj.swing.junit.ant; import static org.apache.tools.ant.taskdefs.optional.junit.XMLConstants.ERROR; import static org.apache.tools.ant.taskdefs.optional.junit.XMLConstants.FAILURE; import static org.apache.tools.ant.taskdefs.optional.junit.XMLConstants.SYSTEM_ERR; import static org.apache.tools.ant.taskdefs.optional.junit.XMLConstants.SYSTEM_OUT; import static org.apache.tools.ant.taskdefs.optional.junit.XMLConstants.TESTSUITE; import java.io.OutputStream; import junit.framework.AssertionFailedError; import junit.framework.Test; import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter; import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest; import org.assertj.swing.junit.xml.XmlDocument; import org.assertj.swing.junit.xml.XmlNode; /** * Understands a copy of the original <code>XMLJUnitResultFormatter</code>, with flexibility for extension. * * @author Alex Ruiz */ public class XmlJUnitResultFormatter implements JUnitResultFormatter { private XmlNode xmlRoot; private OutputStream out; // where to write the log to private final TestCollection tests; private final SuiteXmlNodeWriter suiteXmlNodeWriter; private final EnvironmentXmlNodeWriter environmentXmlNodeWriter; private final TestXmlNodeWriter testXmlNodeWriter; private final XmlOutputWriter xmlOutputWriter; /** * Creates a new <code>{@link XmlJUnitResultFormatter}</code>. */ public XmlJUnitResultFormatter() { tests = new TestCollection(); suiteXmlNodeWriter = new SuiteXmlNodeWriter(); environmentXmlNodeWriter = new EnvironmentXmlNodeWriter(); testXmlNodeWriter = new TestXmlNodeWriter(); xmlOutputWriter = new XmlOutputWriter(); } // for testing only final TestCollection tests() { return tests; } /** * Sets the stream the formatter is supposed to write its results to. * * @param out the output stream to use. */ @Override public final void setOutput(OutputStream out) { this.out = out; } /** * This is what the test has written to <code>System.out</code>, * * @param out the <code>String</code> to write. */ @Override public final void setSystemOutput(String out) { formatOutput(SYSTEM_OUT, out); } /** * This is what the test has written to <code>System.err</code>. * * @param out the <code>String</code> to write. */ @Override public final void setSystemError(String out) { formatOutput(SYSTEM_ERR, out); } private void formatOutput(String type, String output) { xmlRoot.addNewNode(type).addCdata(output); } protected final XmlNode xmlRootNode() { return xmlRoot; } /** * The whole test suite started. This method starts creation of the XML report. * * @param suite the test suite. * @throws ExceptionInInitializerError if the underlying XML document could not be created. */ @Override public final void startTestSuite(JUnitTest suite) { XmlDocument document = new XmlDocument(); xmlRoot = document.newRoot(TESTSUITE); suiteXmlNodeWriter.writeSuiteName(xmlRoot, suite).writeSuiteProperties(xmlRoot, suite); environmentXmlNodeWriter.writeHostName(xmlRoot).writeTimestamp(xmlRoot); onStartTestSuite(suite); } /** * Hook for subclasses to add extra functionality after the whole test suite started. * * @param suite the test suite. */ protected void onStartTestSuite(@SuppressWarnings("unused") JUnitTest suite) { } /** * The whole test suite ended. This method finishes writing the XML report and writes its contents to this formatter's * <code>{@link OutputStream}</code>. * * @param suite the test suite. * @throws org.apache.tools.ant.BuildException on error. */ @Override public final void endTestSuite(JUnitTest suite) { suiteXmlNodeWriter.writeSuiteStatistics(xmlRoot, suite); if (out == null) return; xmlOutputWriter.write(xmlRoot, out); } /** * A new test is started. * * @param test the test. */ @Override public final void startTest(Test test) { tests.started(test); } /** * A test is finished. * * @param test the test. */ @Override public final void endTest(Test test) { if (!tests.wasStarted(test)) startTest(test); XmlNode testNode = xmlNodeForFinished(test); testXmlNodeWriter.writeTestExecutionTime(testNode, tests.startTimeOf(test)); } private XmlNode xmlNodeForFinished(Test test) { if (tests.wasFailed(test)) return tests.xmlNodeFor(test); XmlNode newTestXmlNode = testXmlNodeWriter.addNewTestXmlNode(xmlRoot, test); tests.addXmlNode(test, newTestXmlNode); return newTestXmlNode; } /** * A test failed. * * @param test the test. * @param failedAssertion the failed assertion. */ @Override public final void addFailure(Test test, AssertionFailedError failedAssertion) { addFailure(test, (Throwable) failedAssertion); } /** * A test failed. * * @param test the test. * @param error the exception. */ public final void addFailure(Test test, Throwable error) { XmlNode errorXmlNode = formatError(FAILURE, test, error); onFailureOrError(test, error, errorXmlNode); } /** * An error occurred while running the test. * * @param test the test. * @param error the error. */ @Override public final void addError(Test test, Throwable error) { XmlNode errorXmlNode = formatError(ERROR, test, error); onFailureOrError(test, error, errorXmlNode); } private XmlNode formatError(String type, Test test, Throwable error) { if (test != null) { endTest(test); tests.failed(test); } XmlNode errorXmlNode = xmlForFailed(test).addNewNode(type); writeErrorAndStackTrace(error, errorXmlNode); return errorXmlNode; } private XmlNode xmlForFailed(Test test) { if (test != null) return tests.xmlNodeFor(test); return xmlRoot; } /** * Writes the stack trace and message of the given error to the given XML node. * * @param error the given error. * @param errorXmlNode the XML node to write to. */ protected final void writeErrorAndStackTrace(Throwable error, XmlNode errorXmlNode) { testXmlNodeWriter.writeErrorAndStackTrace(errorXmlNode, error); } /** * Hook for subclasses to add extra functionality after a test failure or a test execution error. * * @param test the executing test. * @param error the reason of the failure or error. * @param errorXmlNode the XML element containing information about the test failure or error. */ protected void onFailureOrError(@SuppressWarnings("unused") Test test, @SuppressWarnings("unused") Throwable error, @SuppressWarnings("unused") XmlNode errorXmlNode) { } }