Repository: cassandra Updated Branches: refs/heads/trunk f60a201a3 -> ad58bf7c7
ant test-all results incomplete when parsed (part 2) patch by aweisberg; reviewed by jasobrown for CASSANDRA-9463 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/1352ebd6 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/1352ebd6 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/1352ebd6 Branch: refs/heads/trunk Commit: 1352ebd61d2b0949baa9cfb6132985cbfcb58fca Parents: 302eb46 Author: Jason Brown <[email protected]> Authored: Fri May 29 10:07:59 2015 -0700 Committer: Jason Brown <[email protected]> Committed: Fri May 29 10:07:59 2015 -0700 ---------------------------------------------------------------------- build.xml | 16 +- .../CassandraBriefJUnitResultFormatter.java | 312 +++++++++++++++ .../CassandraXMLJUnitResultFormatter.java | 380 +++++++++++++++++++ 3 files changed, 701 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/1352ebd6/build.xml ---------------------------------------------------------------------- diff --git a/build.xml b/build.xml index bb401ee..ecde9f9 100644 --- a/build.xml +++ b/build.xml @@ -443,7 +443,8 @@ <dependency groupId="org.caffinitas.ohc" artifactId="ohc-core"/> <dependency groupId="org.openjdk.jmh" artifactId="jmh-core"/> <dependency groupId="org.openjdk.jmh" artifactId="jmh-generator-annprocess"/> - <dependency groupId="net.ju-n.compile-command-annotations" artifactId="compile-command-annotations"/> + <dependency groupId="net.ju-n.compile-command-annotations" artifactId="compile-command-annotations"/> + <dependency groupId="org.apache.ant" artifactId="ant-junit" version="1.9.4" /> </artifact:pom> <artifact:pom id="coverage-deps-pom" @@ -1118,7 +1119,7 @@ <attribute name="exclude" default="" /> <attribute name="filelist" default="" /> <attribute name="poffset" default="0"/> - <attribute name="outsubdir" default=""/> + <attribute name="testtag" default=""/> <attribute name="usejacoco" default="no"/> <sequential> @@ -1130,11 +1131,11 @@ <echo message="running @{suitename} tests"/> <mkdir dir="${build.test.dir}/cassandra"/> <mkdir dir="${build.test.dir}/output"/> - <mkdir dir="${build.test.dir}/output/@{outsubdir}"/> + <mkdir dir="${build.test.dir}/output/@{testtag}"/> <junit fork="on" forkmode="@{forkmode}" failureproperty="testfailed" maxmemory="1024m" timeout="@{timeout}"> <sysproperty key="net.sourceforge.cobertura.datafile" file="${cobertura.datafile}"/> - <formatter type="xml" usefile="true"/> - <formatter type="brief" usefile="false"/> + <formatter classname="org.apache.cassandra.CassandraXMLJUnitResultFormatter" extension=".xml" usefile="true"/> + <formatter classname="org.apache.cassandra.CassandraBriefJUnitResultFormatter" usefile="false"/> <jvmarg value="-Dstorage-config=${test.conf}"/> <jvmarg value="-Djava.awt.headless=true"/> <!-- Cassandra 3.0+ needs <jvmarg line="... ${additionalagent}" /> here! (not value=) --> @@ -1146,6 +1147,7 @@ <jvmarg value="-Dcassandra.test.use_prepared=${cassandra.test.use_prepared}"/> <jvmarg value="-Dcassandra.test.offsetseed=@{poffset}"/> <jvmarg value="-Dcassandra.test.sstableformatdevelopment=true"/> + <jvmarg value="-Dcassandra.testtag=@{testtag}"/> <optjvmargs/> <classpath> <path refid="cassandra.classpath" /> @@ -1156,7 +1158,7 @@ <include name="**/*.jar" /> </fileset> </classpath> - <batchtest todir="${build.test.dir}/output/@{outsubdir}"> + <batchtest todir="${build.test.dir}/output/@{testtag}"> <fileset dir="@{inputdir}" includes="@{filter}" excludes="@{exclude}"/> <filelist dir="@{inputdir}" files="@{filelist}"/> </batchtest> @@ -1272,7 +1274,7 @@ <fileset file="${test.conf}/commitlog_compression.yaml"/> </concat> <echo>Compressed config: ${compressed_yaml}</echo> - <testmacro suitename="unit" inputdir="${test.unit.src}" exclude="**/pig/*.java" timeout="${test.timeout}" outsubdir="compression"> + <testmacro suitename="unit" inputdir="${test.unit.src}" exclude="**/pig/*.java" timeout="${test.timeout}" testtag="compression"> <jvmarg value="-Dlegacy-sstable-root=${test.data}/legacy-sstables"/> <jvmarg value="-Dinvalid-legacy-sstable-root=${test.data}/invalid-legacy-sstables"/> <jvmarg value="-Dcorrupt-sstable-root=${test.data}/corrupt-sstables"/> http://git-wip-us.apache.org/repos/asf/cassandra/blob/1352ebd6/test/unit/org/apache/cassandra/CassandraBriefJUnitResultFormatter.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/CassandraBriefJUnitResultFormatter.java b/test/unit/org/apache/cassandra/CassandraBriefJUnitResultFormatter.java new file mode 100644 index 0000000..084858f --- /dev/null +++ b/test/unit/org/apache/cassandra/CassandraBriefJUnitResultFormatter.java @@ -0,0 +1,312 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.cassandra; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringWriter; +import java.text.NumberFormat; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.optional.junit.IgnoredTestListener; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitVersionHelper; +import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.util.StringUtils; + +/** + * Prints plain text output of the test to a specified Writer. + * Inspired by the PlainJUnitResultFormatter. + * + * @see FormatterElement + * @see PlainJUnitResultFormatter + */ +public class CassandraBriefJUnitResultFormatter implements JUnitResultFormatter, IgnoredTestListener { + + private static final double ONE_SECOND = 1000.0; + + private static final String tag = System.getProperty("cassandra.testtag", ""); + + /** + * Where to write the log to. + */ + private OutputStream out; + + /** + * Used for writing the results. + */ + private BufferedWriter output; + + /** + * Used as part of formatting the results. + */ + private StringWriter results; + + /** + * Used for writing formatted results to. + */ + private BufferedWriter resultWriter; + + /** + * Formatter for timings. + */ + private NumberFormat numberFormat = NumberFormat.getInstance(); + + /** + * Output suite has written to System.out + */ + private String systemOutput = null; + + /** + * Output suite has written to System.err + */ + private String systemError = null; + + /** + * Constructor for BriefJUnitResultFormatter. + */ + public CassandraBriefJUnitResultFormatter() { + results = new StringWriter(); + resultWriter = new BufferedWriter(results); + } + + /** + * Sets the stream the formatter is supposed to write its results to. + * @param out the output stream to write to + */ + public void setOutput(OutputStream out) { + this.out = out; + output = new BufferedWriter(new java.io.OutputStreamWriter(out)); + } + + /** + * @see JUnitResultFormatter#setSystemOutput(String) + */ + /** {@inheritDoc}. */ + public void setSystemOutput(String out) { + systemOutput = out; + } + + /** + * @see JUnitResultFormatter#setSystemError(String) + */ + /** {@inheritDoc}. */ + public void setSystemError(String err) { + systemError = err; + } + + + /** + * The whole testsuite started. + * @param suite the test suite + */ + public void startTestSuite(JUnitTest suite) { + if (output == null) { + return; // Quick return - no output do nothing. + } + StringBuffer sb = new StringBuffer("Testsuite: "); + String n = suite.getName(); + if (n != null && !tag.isEmpty()) + n = n + "-" + tag; + sb.append(n); + sb.append(StringUtils.LINE_SEP); + try { + output.write(sb.toString()); + output.flush(); + } catch (IOException ex) { + throw new BuildException(ex); + } + } + + /** + * The whole testsuite ended. + * @param suite the test suite + */ + public void endTestSuite(JUnitTest suite) { + StringBuffer sb = new StringBuffer("Tests run: "); + sb.append(suite.runCount()); + sb.append(", Failures: "); + sb.append(suite.failureCount()); + sb.append(", Errors: "); + sb.append(suite.errorCount()); + sb.append(", Skipped: "); + sb.append(suite.skipCount()); + sb.append(", Time elapsed: "); + sb.append(numberFormat.format(suite.getRunTime() / ONE_SECOND)); + sb.append(" sec"); + sb.append(StringUtils.LINE_SEP); + sb.append(StringUtils.LINE_SEP); + + // append the err and output streams to the log + if (systemOutput != null && systemOutput.length() > 0) { + sb.append("------------- Standard Output ---------------") + .append(StringUtils.LINE_SEP) + .append(systemOutput) + .append("------------- ---------------- ---------------") + .append(StringUtils.LINE_SEP); + } + + if (systemError != null && systemError.length() > 0) { + sb.append("------------- Standard Error -----------------") + .append(StringUtils.LINE_SEP) + .append(systemError) + .append("------------- ---------------- ---------------") + .append(StringUtils.LINE_SEP); + } + + if (output != null) { + try { + output.write(sb.toString()); + resultWriter.close(); + output.write(results.toString()); + } catch (IOException ex) { + throw new BuildException(ex); + } finally { + try { + output.flush(); + } catch (IOException ex) { + // swallow, there has likely been an exception before this + } + if (out != System.out && out != System.err) { + FileUtils.close(out); + } + } + } + } + + /** + * A test started. + * @param test a test + */ + public void startTest(Test test) { + } + + /** + * A test ended. + * @param test a test + */ + public void endTest(Test test) { + } + + /** + * Interface TestListener for JUnit <= 3.4. + * + * <p>A Test failed. + * @param test a test + * @param t the exception thrown by the test + */ + public void addFailure(Test test, Throwable t) { + formatError("\tFAILED", test, t); + } + + /** + * Interface TestListener for JUnit > 3.4. + * + * <p>A Test failed. + * @param test a test + * @param t the assertion failed by the test + */ + public void addFailure(Test test, AssertionFailedError t) { + addFailure(test, (Throwable) t); + } + + /** + * A test caused an error. + * @param test a test + * @param error the error thrown by the test + */ + public void addError(Test test, Throwable error) { + formatError("\tCaused an ERROR", test, error); + } + + /** + * Format the test for printing.. + * @param test a test + * @return the formatted testname + */ + protected String formatTest(Test test) { + if (test == null) { + return "Null Test: "; + } else { + if (!tag.isEmpty()) + return "Testcase: " + test.toString() + "-" + tag + ":"; + return "Testcase: " + test.toString() + ":"; + } + } + + /** + * Format an error and print it. + * @param type the type of error + * @param test the test that failed + * @param error the exception that the test threw + */ + protected synchronized void formatError(String type, Test test, + Throwable error) { + if (test != null) { + endTest(test); + } + + try { + resultWriter.write(formatTest(test) + type); + resultWriter.newLine(); + resultWriter.write(String.valueOf(error.getMessage())); + resultWriter.newLine(); + String strace = JUnitTestRunner.getFilteredTrace(error); + resultWriter.write(strace); + resultWriter.newLine(); + resultWriter.newLine(); + } catch (IOException ex) { + throw new BuildException(ex); + } + } + + + public void testIgnored(Test test) { + formatSkip(test, JUnitVersionHelper.getIgnoreMessage(test)); + } + + + public void formatSkip(Test test, String message) { + if (test != null) { + endTest(test); + } + + try { + resultWriter.write(formatTest(test) + "SKIPPED"); + if (message != null) { + resultWriter.write(": "); + resultWriter.write(message); + } + resultWriter.newLine(); + } catch (IOException ex) { + throw new BuildException(ex); + } + + } + + public void testAssumptionFailure(Test test, Throwable cause) { + formatSkip(test, cause.getMessage()); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/cassandra/blob/1352ebd6/test/unit/org/apache/cassandra/CassandraXMLJUnitResultFormatter.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/CassandraXMLJUnitResultFormatter.java b/test/unit/org/apache/cassandra/CassandraXMLJUnitResultFormatter.java new file mode 100644 index 0000000..066315d --- /dev/null +++ b/test/unit/org/apache/cassandra/CassandraXMLJUnitResultFormatter.java @@ -0,0 +1,380 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.cassandra; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Properties; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.optional.junit.IgnoredTestListener; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitResultFormatter; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner; +import org.apache.tools.ant.taskdefs.optional.junit.JUnitVersionHelper; +import org.apache.tools.ant.taskdefs.optional.junit.XMLConstants; +import org.apache.tools.ant.util.DOMElementWriter; +import org.apache.tools.ant.util.DateUtils; +import org.apache.tools.ant.util.FileUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Text; + + +/** + * Prints XML output of the test to a specified Writer. + * + * @see FormatterElement + */ + +public class CassandraXMLJUnitResultFormatter implements JUnitResultFormatter, XMLConstants, IgnoredTestListener { + + private static final double ONE_SECOND = 1000.0; + + /** constant for unnnamed testsuites/cases */ + private static final String UNKNOWN = "unknown"; + + private static DocumentBuilder getDocumentBuilder() { + try { + return DocumentBuilderFactory.newInstance().newDocumentBuilder(); + } catch (final Exception exc) { + throw new ExceptionInInitializerError(exc); + } + } + + private static final String tag = System.getProperty("cassandra.testtag", ""); + + /** + * The XML document. + */ + private Document doc; + + /** + * The wrapper for the whole testsuite. + */ + private Element rootElement; + + /** + * Element for the current test. + * + * The keying of this map is a bit of a hack: tests are keyed by caseName(className) since + * the Test we get for Test-start isn't the same as the Test we get during test-assumption-fail, + * so we can't easily match Test objects without manually iterating over all keys and checking + * individual fields. + */ + private final Hashtable<String, Element> testElements = new Hashtable<String, Element>(); + + /** + * tests that failed. + */ + private final Hashtable failedTests = new Hashtable(); + + /** + * Tests that were skipped. + */ + private final Hashtable<String, Test> skippedTests = new Hashtable<String, Test>(); + /** + * Tests that were ignored. See the note above about the key being a bit of a hack. + */ + private final Hashtable<String, Test> ignoredTests = new Hashtable<String, Test>(); + /** + * Timing helper. + */ + private final Hashtable<String, Long> testStarts = new Hashtable<String, Long>(); + /** + * Where to write the log to. + */ + private OutputStream out; + + /** No arg constructor. */ + public CassandraXMLJUnitResultFormatter() { + } + + /** {@inheritDoc}. */ + public void setOutput(final OutputStream out) { + this.out = out; + } + + /** {@inheritDoc}. */ + public void setSystemOutput(final String out) { + formatOutput(SYSTEM_OUT, out); + } + + /** {@inheritDoc}. */ + public void setSystemError(final String out) { + formatOutput(SYSTEM_ERR, out); + } + + /** + * The whole testsuite started. + * @param suite the testsuite. + */ + public void startTestSuite(final JUnitTest suite) { + doc = getDocumentBuilder().newDocument(); + rootElement = doc.createElement(TESTSUITE); + String n = suite.getName(); +// if (n != null && !tag.isEmpty()) +// n = n + "-" + tag; + rootElement.setAttribute(ATTR_NAME, n == null ? UNKNOWN : n); + + //add the timestamp + final String timestamp = DateUtils.format(new Date(), + DateUtils.ISO8601_DATETIME_PATTERN); + rootElement.setAttribute(TIMESTAMP, timestamp); + //and the hostname. + rootElement.setAttribute(HOSTNAME, getHostname()); + + // Output properties + final Element propsElement = doc.createElement(PROPERTIES); + rootElement.appendChild(propsElement); + final Properties props = suite.getProperties(); + if (props != null) { + final Enumeration e = props.propertyNames(); + while (e.hasMoreElements()) { + final String name = (String) e.nextElement(); + final Element propElement = doc.createElement(PROPERTY); + propElement.setAttribute(ATTR_NAME, name); + propElement.setAttribute(ATTR_VALUE, props.getProperty(name)); + propsElement.appendChild(propElement); + } + } + } + + /** + * get the local hostname + * @return the name of the local host, or "localhost" if we cannot work it out + */ + private String getHostname() { + String hostname = "localhost"; + try { + final InetAddress localHost = InetAddress.getLocalHost(); + if (localHost != null) { + hostname = localHost.getHostName(); + } + } catch (final UnknownHostException e) { + // fall back to default 'localhost' + } + return hostname; + } + + /** + * The whole testsuite ended. + * @param suite the testsuite. + * @throws BuildException on error. + */ + public void endTestSuite(final JUnitTest suite) throws BuildException { + rootElement.setAttribute(ATTR_TESTS, "" + suite.runCount()); + rootElement.setAttribute(ATTR_FAILURES, "" + suite.failureCount()); + rootElement.setAttribute(ATTR_ERRORS, "" + suite.errorCount()); + rootElement.setAttribute(ATTR_SKIPPED, "" + suite.skipCount()); + rootElement.setAttribute( + ATTR_TIME, "" + (suite.getRunTime() / ONE_SECOND)); + if (out != null) { + Writer wri = null; + try { + wri = new BufferedWriter(new OutputStreamWriter(out, "UTF8")); + wri.write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); + (new DOMElementWriter()).write(rootElement, wri, 0, " "); + } catch (final IOException exc) { + throw new BuildException("Unable to write log file", exc); + } finally { + if (wri != null) { + try { + wri.flush(); + } catch (final IOException ex) { + // ignore + } + } + if (out != System.out && out != System.err) { + FileUtils.close(wri); + } + } + } + } + + /** + * Interface TestListener. + * + * <p>A new Test is started. + * @param t the test. + */ + public void startTest(final Test t) { + testStarts.put(createDescription(t), System.currentTimeMillis()); + } + + private static String createDescription(final Test test) throws BuildException { + if (!tag.isEmpty()) + return JUnitVersionHelper.getTestCaseName(test) + "-" + tag +"(" + JUnitVersionHelper.getTestCaseClassName(test) + ")"; + return JUnitVersionHelper.getTestCaseName(test) + "(" + JUnitVersionHelper.getTestCaseClassName(test) + ")"; + } + + /** + * Interface TestListener. + * + * <p>A Test is finished. + * @param test the test. + */ + public void endTest(final Test test) { + final String testDescription = createDescription(test); + + // Fix for bug #5637 - if a junit.extensions.TestSetup is + // used and throws an exception during setUp then startTest + // would never have been called + if (!testStarts.containsKey(testDescription)) { + startTest(test); + } + Element currentTest; + if (!failedTests.containsKey(test) && !skippedTests.containsKey(testDescription) && !ignoredTests.containsKey(testDescription)) { + currentTest = doc.createElement(TESTCASE); + String n = JUnitVersionHelper.getTestCaseName(test); + if (n != null && !tag.isEmpty()) + n = n + "-" + tag; + currentTest.setAttribute(ATTR_NAME, + n == null ? UNKNOWN : n); + // a TestSuite can contain Tests from multiple classes, + // even tests with the same name - disambiguate them. + currentTest.setAttribute(ATTR_CLASSNAME, + JUnitVersionHelper.getTestCaseClassName(test)); + rootElement.appendChild(currentTest); + testElements.put(createDescription(test), currentTest); + } else { + currentTest = testElements.get(testDescription); + } + + final Long l = testStarts.get(createDescription(test)); + currentTest.setAttribute(ATTR_TIME, + "" + ((System.currentTimeMillis() - l) / ONE_SECOND)); + } + + /** + * Interface TestListener for JUnit <= 3.4. + * + * <p>A Test failed. + * @param test the test. + * @param t the exception. + */ + public void addFailure(final Test test, final Throwable t) { + formatError(FAILURE, test, t); + } + + /** + * Interface TestListener for JUnit > 3.4. + * + * <p>A Test failed. + * @param test the test. + * @param t the assertion. + */ + public void addFailure(final Test test, final AssertionFailedError t) { + addFailure(test, (Throwable) t); + } + + /** + * Interface TestListener. + * + * <p>An error occurred while running the test. + * @param test the test. + * @param t the error. + */ + public void addError(final Test test, final Throwable t) { + formatError(ERROR, test, t); + } + + private void formatError(final String type, final Test test, final Throwable t) { + if (test != null) { + endTest(test); + failedTests.put(test, test); + } + + final Element nested = doc.createElement(type); + Element currentTest; + if (test != null) { + currentTest = testElements.get(createDescription(test)); + } else { + currentTest = rootElement; + } + + currentTest.appendChild(nested); + + final String message = t.getMessage(); + if (message != null && message.length() > 0) { + nested.setAttribute(ATTR_MESSAGE, t.getMessage()); + } + nested.setAttribute(ATTR_TYPE, t.getClass().getName()); + + final String strace = JUnitTestRunner.getFilteredTrace(t); + final Text trace = doc.createTextNode(strace); + nested.appendChild(trace); + } + + private void formatOutput(final String type, final String output) { + final Element nested = doc.createElement(type); + rootElement.appendChild(nested); + nested.appendChild(doc.createCDATASection(output)); + } + + public void testIgnored(final Test test) { + formatSkip(test, JUnitVersionHelper.getIgnoreMessage(test)); + if (test != null) { + ignoredTests.put(createDescription(test), test); + } + } + + + public void formatSkip(final Test test, final String message) { + if (test != null) { + endTest(test); + } + + final Element nested = doc.createElement("skipped"); + + if (message != null) { + nested.setAttribute("message", message); + } + + Element currentTest; + if (test != null) { + currentTest = testElements.get(createDescription(test)); + } else { + currentTest = rootElement; + } + + currentTest.appendChild(nested); + + } + + public void testAssumptionFailure(final Test test, final Throwable failure) { + formatSkip(test, failure.getMessage()); + skippedTests.put(createDescription(test), test); + + } +} // XMLJUnitResultFormatter \ No newline at end of file
