Author: julien(a)jboss.com
Date: 2007-10-22 06:25:33 -0400 (Mon, 22 Oct 2007)
New Revision: 8731
Added:
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/AbstractJUnitReport.java
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/JUnitTestsuiteReport.java
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/StringUtils.java
modules/test/trunk/unit/src/resources/jboss-unit-jar/org/jboss/unit/report/
modules/test/trunk/unit/src/resources/jboss-unit-jar/org/jboss/unit/report/impl/
modules/test/trunk/unit/src/resources/jboss-unit-jar/org/jboss/unit/report/impl/junit/
modules/test/trunk/unit/src/resources/jboss-unit-jar/org/jboss/unit/report/impl/junit/junit-frames.xsl
Modified:
modules/test/trunk/tooling/build.xml
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/HTMLReportsType.java
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/ReportsType.java
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/TestsType.java
modules/test/trunk/unit/src/main/org/jboss/test/unit/sample/SampleTests.java
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/JUnitReporter.java
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/ByteArrayOutputStreamExt.java
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/Main.java
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/MainBuilder.java
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/SystemOutputManager.java
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/SystemOutputView.java
Log:
- improved JUnit XML reporting
- implemented HTML reporting
Modified: modules/test/trunk/tooling/build.xml
===================================================================
--- modules/test/trunk/tooling/build.xml 2007-10-21 15:33:41 UTC (rev 8730)
+++ modules/test/trunk/tooling/build.xml 2007-10-22 10:25:33 UTC (rev 8731)
@@ -266,10 +266,10 @@
<reports>
<!-- if toDir for xml reports doesn't exist it'll be created
-->
<!-- at the moment it produces xmls in junit format -->
- <xml toDir="./output/test-results"/>
+ <xml toDir="./output/test-results/xml"/>
<!-- html reports uses junit reporting task and will reuse reports
generated by <xml> task-->
- <html toDir="./output/test-results"/>
+ <html toDir="./output/test-results/html"/>
</reports>
<sysproperty key="toto" value="totoValue"/>
Modified:
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/HTMLReportsType.java
===================================================================
---
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/HTMLReportsType.java 2007-10-21
15:33:41 UTC (rev 8730)
+++
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/HTMLReportsType.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -43,5 +43,4 @@
{
this.toDir = toDir;
}
-
}
Modified: modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/ReportsType.java
===================================================================
---
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/ReportsType.java 2007-10-21
15:33:41 UTC (rev 8730)
+++
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/ReportsType.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -56,12 +56,12 @@
htmlReports = html;
}
- public XMLReportsType getXmlReports()
+ public XMLReportsType getXMLReports()
{
return xmlReports;
}
- public HTMLReportsType getHtmlReports()
+ public HTMLReportsType getHTMLReports()
{
return htmlReports;
}
Modified: modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/TestsType.java
===================================================================
---
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/TestsType.java 2007-10-21
15:33:41 UTC (rev 8730)
+++
modules/test/trunk/tooling/src/main/org/jboss/unit/tooling/ant/TestsType.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -187,14 +187,16 @@
javaTask.createArg().setValue(OPT_SUITE_NAME + "=" + getSuiteName());
}
-
-
- if (getReports() != null && getReports().getXmlReports() != null)
+ if (getReports() != null && getReports().getXMLReports() != null)
{
- javaTask.createArg().setValue(OPT_XML_REPORT_DIR + "=" +
getReports().getXmlReports().getToDir());
+ javaTask.createArg().setValue(OPT_XML_REPORT_DIR + "=" +
getReports().getXMLReports().getToDir());
}
-
+ if (getReports() != null && getReports().getHTMLReports() != null)
+ {
+ javaTask.createArg().setValue(OPT_HTML_REPORT_DIR + "=" +
getReports().getHTMLReports().getToDir());
+ }
+
Set<String> includeIds = new HashSet<String>();
Set<String> includeKeywords = new HashSet<String>();
@@ -203,9 +205,6 @@
Set<String> excludeKeywords = new HashSet<String>();
-
-
-
for (IncludeType include : includes)
{
//Check attributes consistency
Modified: modules/test/trunk/unit/src/main/org/jboss/test/unit/sample/SampleTests.java
===================================================================
---
modules/test/trunk/unit/src/main/org/jboss/test/unit/sample/SampleTests.java 2007-10-21
15:33:41 UTC (rev 8730)
+++
modules/test/trunk/unit/src/main/org/jboss/test/unit/sample/SampleTests.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -22,22 +22,23 @@
******************************************************************************/
package org.jboss.test.unit.sample;
+import org.jboss.unit.report.impl.junit.JUnitTestsuiteReport;
import org.jboss.unit.report.impl.writer.PrintListener;
-import org.jboss.unit.report.impl.junit.JUnitReporter;
import org.jboss.unit.runner.TestRunner;
import org.jboss.unit.runner.TestRunnerEventListener;
+import org.jboss.unit.runner.impl.TestRunnerContextSupport;
import org.jboss.unit.runner.impl.TestRunnerEventBroadcaster;
-import org.jboss.unit.runner.impl.TestRunnerContextSupport;
+import org.jboss.unit.runner.model.BuilderException;
import org.jboss.unit.runner.model.ModelBuilder;
import org.jboss.unit.runner.model.TestSuiteDef;
-import org.jboss.unit.runner.model.BuilderException;
import org.jboss.unit.tooling.SystemOutputManager;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
+import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
-import java.io.IOException;
/**
* @author <a href="mailto:julien@jboss.org">Julien Viet</a>
@@ -86,9 +87,34 @@
TestRunner runner = suite.createRunner();
- TestRunnerEventListener junitReporter = new
JUnitReporter("output/tests", SampleTests.class.getName());
- // add listeners
+ File xmlDir = new File("output/tests/xml");
+ File htmlDir = new File("output/tests/html");
+ if (!xmlDir.exists())
+ {
+ xmlDir.mkdirs();
+ }
+ else
+ {
+ if (!xmlDir.isDirectory())
+ {
+ throw new AssertionError();
+ }
+ }
+ if (!htmlDir.exists())
+ {
+ htmlDir.mkdirs();
+ }
+ else
+ {
+ if (!htmlDir.isDirectory())
+ {
+ throw new AssertionError();
+ }
+ }
+
+ TestRunnerEventListener junitReporter = new JUnitTestsuiteReport(xmlDir,
htmlDir);
+
TestRunnerEventBroadcaster broadcaster = new TestRunnerEventBroadcaster();
broadcaster.addListener(junitReporter);
broadcaster.addListener(new PrintListener());
Added:
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/AbstractJUnitReport.java
===================================================================
---
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/AbstractJUnitReport.java
(rev 0)
+++
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/AbstractJUnitReport.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -0,0 +1,264 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2006, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org. *
+ ******************************************************************************/
+package org.jboss.unit.report.impl.junit;
+
+import org.jboss.unit.Failure;
+import org.jboss.unit.TestId;
+import org.jboss.unit.info.TestInfo;
+import org.jboss.unit.runner.TestResult;
+import org.jboss.unit.runner.TestRunnerEvent;
+import org.jboss.unit.runner.TestRunnerEventListener;
+import org.jboss.unit.runner.event.EndRunnerEvent;
+import org.jboss.unit.runner.event.EndTestCaseEvent;
+import org.jboss.unit.runner.event.EndTestSuiteEvent;
+import org.jboss.unit.runner.event.RunnerFailureEvent;
+import org.jboss.unit.runner.event.StartRunnerEvent;
+import org.jboss.unit.runner.event.StartTestCaseEvent;
+import org.jboss.unit.runner.event.StartTestSuiteEvent;
+import org.jboss.unit.tooling.SystemOutputManager;
+import org.jboss.unit.tooling.SystemOutputView;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public abstract class AbstractJUnitReport implements TestRunnerEventListener
+{
+
+ /** The tested classes stack. */
+ private TestSuite current;
+
+ public void onEvent(TestRunnerEvent event)
+ {
+ if (event instanceof StartRunnerEvent)
+ {
+ handle((StartRunnerEvent) event);
+ }
+ else if (event instanceof EndRunnerEvent)
+ {
+ handle((EndRunnerEvent)event);
+ }
+ else if (event instanceof RunnerFailureEvent)
+ {
+ handle((RunnerFailureEvent) event);
+ }
+ else if (event instanceof StartTestSuiteEvent)
+ {
+ handle((StartTestSuiteEvent)event);
+ }
+ else if (event instanceof EndTestSuiteEvent)
+ {
+ handle((EndTestSuiteEvent)event);
+ }
+ else if (event instanceof StartTestCaseEvent)
+ {
+ handle((StartTestCaseEvent) event);
+ }
+ else if (event instanceof EndTestCaseEvent)
+ {
+ handle((EndTestCaseEvent) event);
+ }
+ }
+
+ protected abstract void startRunner();
+
+ protected abstract void endRunner();
+
+ protected abstract void runnerFailure(TestSuite testSuite, Failure failure);
+
+ protected abstract void endTestCase(TestSuite testSuite, String testName, TestResult
result);
+
+ protected abstract void startTestSuite(TestSuite testSuite);
+
+ protected abstract void endTestSuite(TestSuite testSuite);
+
+ private void handle(StartRunnerEvent event)
+ {
+ current = new TestSuite(null, "");
+
+ //
+ startTestSuite(current);
+
+ //
+ startRunner();
+ }
+
+ private void handle(EndRunnerEvent event)
+ {
+ TestSuite tmp = current;
+ current = null;
+
+ //
+ endTestSuite(tmp);
+
+ //
+ endRunner();
+ }
+
+ private void handle(StartTestSuiteEvent event)
+ {
+ current = new TestSuite(current, event.getTestInfo().getName());
+
+ //
+ startTestSuite(current);
+ }
+
+ private void handle(EndTestSuiteEvent event)
+ {
+ TestSuite testSuite = current;
+ current = current.parent;
+
+ //
+ endTestSuite(testSuite);
+ }
+
+ private void handle(StartTestCaseEvent event)
+ {
+ current.startedTests.put(event.getTestId(), event.getTestInfo());
+ }
+
+ private void handle(RunnerFailureEvent event)
+ {
+ current.tests++;
+ current.errors++;
+
+ //
+ runnerFailure(current, event.getFailure());
+ }
+
+ private void handle(EndTestCaseEvent event)
+ {
+ TestId testId = event.getTestId();
+ TestResult result = event.getTestResult();
+ TestInfo info = current.startedTests.get(testId);
+
+ // remove test from started List
+ current.startedTests.remove(testId);
+
+ /** Adding testcase name */
+ StringBuffer testName = new StringBuffer(info.getName());
+ Iterator<String> i = result.getParametrization().keySet().iterator();
+ if (i.hasNext())
+ {
+ testName.append("?");
+ while (i.hasNext())
+ {
+ String parameterName = i.next();
+ String value = result.getParametrization().get(parameterName);
+ testName.append(parameterName).append("=").append(value);
+ if(i.hasNext())
+ {
+ testName.append("&");
+ }
+ }
+ }
+
+ //
+ current.durationMillis += result.getDurationMillis();
+ current.tests++;
+
+ //
+ endTestCase(current, testName.toString(), result);
+ }
+
+ public class TestSuite
+ {
+
+ /** . */
+ final TestSuite parent;
+
+ /** . */
+ final String name;
+
+ /** . */
+ long durationMillis;
+
+ /** The test count */
+ int tests;
+
+ /** The error count */
+ int errors;
+
+ /** The failed count */
+ int failed;
+
+ /** The started Tests */
+ Map<TestId, TestInfo> startedTests = new HashMap<TestId, TestInfo>();
+
+// /** . */
+// List<Element> children = new ArrayList<Element>();
+
+ /** The view of the system output. */
+ SystemOutputView view = SystemOutputManager.getInstance().createView(false);
+
+ /**
+ * Todo: set properties
+ *
+ * @param name
+ */
+ TestSuite(TestSuite parent, String name)
+ {
+ this.parent = parent;
+ this.name = name;
+ }
+
+ public StringBuffer getFQN()
+ {
+ if (parent == null)
+ {
+ return new StringBuffer("_none_");
+ }
+ else
+ {
+ List<TestSuite> tmp = new ArrayList<TestSuite>();
+ for (TestSuite current = this;current.parent != null;current =
current.parent)
+ {
+ tmp.add(current);
+ }
+
+ //
+ Collections.reverse(tmp);
+
+ // Skip the first top that will not participate in the name
+ StringBuffer nb = new StringBuffer();
+ for (Iterator<TestSuite> i = tmp.iterator();i.hasNext();)
+ {
+ TestSuite testSuite = i.next();
+ nb.append(testSuite.name);
+ if (i.hasNext())
+ {
+ nb.append(".");
+ }
+ }
+ return nb;
+ }
+ }
+ }
+}
Modified:
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/JUnitReporter.java
===================================================================
---
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/JUnitReporter.java 2007-10-21
15:33:41 UTC (rev 8730)
+++
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/JUnitReporter.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -76,7 +76,7 @@
if (event instanceof StartRunnerEvent)
{
report.startJUnitTestSuite((StartRunnerEvent) event);
- view = SystemOutputManager.getInstance().createView();
+ view = SystemOutputManager.getInstance().createView(false);
}
else if (event instanceof EndRunnerEvent)
{
Added:
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/JUnitTestsuiteReport.java
===================================================================
---
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/JUnitTestsuiteReport.java
(rev 0)
+++
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/JUnitTestsuiteReport.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -0,0 +1,382 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2006, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org. *
+ ******************************************************************************/
+package org.jboss.unit.report.impl.junit;
+
+import org.jboss.unit.Failure;
+import org.jboss.unit.FailureType;
+import org.jboss.unit.TestId;
+import org.jboss.unit.runner.TestResult;
+import org.jboss.unit.runner.results.TestFailure;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:emuckenh@redhat.com">Emanuel
Muckenhuber</a>
+ * @version $Revision$
+ */
+public class JUnitTestsuiteReport extends AbstractJUnitReport
+{
+
+ /** */
+ public static final String TEST_FILE_NAME_PREFIX = "TEST-";
+
+ /** The formatter for timestamps.*/
+ private static final SimpleDateFormat TIMESTAMP_FORMAT = new
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+
+ /** The formatter for durations.*/
+ private static final NumberFormat DURATION_FORMAT = NumberFormat.getInstance();
+
+ /** The document */
+ private Document testsuitesDocument;
+
+ /** The root element */
+ private Element testsuitesElement;
+
+ /** . */
+ private Map<TestSuite, List<Element>> testSuiteListMap = new
HashMap<TestSuite, List<Element>>();
+
+ /** . */
+ private File htmlReportDir;
+
+ /** . */
+ private File xmlReportDir;
+
+ /** . */
+ private Map<String, Integer> fileNameCounters = new HashMap<String,
Integer>();
+
+ public JUnitTestsuiteReport(File xmlReportDir, File htmlReportDir)
+ {
+ this.xmlReportDir = xmlReportDir;
+ this.htmlReportDir = htmlReportDir;
+ }
+
+ protected void startRunner()
+ {
+ testsuitesDocument = createDocument();
+ testsuitesElement = testsuitesDocument.createElement(XMLConstants.TESTSUITES);
+ }
+
+ protected void endRunner()
+ {
+ if (htmlReportDir != null)
+ {
+ try
+ {
+ InputStream xslIn =
getClass().getResourceAsStream("/org/jboss/unit/report/impl/junit/junit-frames.xsl");
+ Source xmlSource = new DOMSource(testsuitesElement);
+ Source xslSource = new StreamSource(xslIn);
+ TransformerFactory transFact = TransformerFactory.newInstance();
+ Transformer trans = transFact.newTransformer(xslSource);
+ OutputStream os = new ByteArrayOutputStream();
+ Result result = new StreamResult(os);
+ trans.setParameter("output.dir", htmlReportDir.getAbsolutePath());
+ trans.transform(xmlSource, result);
+ }
+ catch (TransformerException e)
+ {
+ e.printStackTrace();
+ }
+
+ //
+ File tmp = new File(htmlReportDir, "TESTS-TestSuites.xml");
+ dump(testsuitesElement, tmp);
+ }
+ }
+
+ protected void runnerFailure(TestSuite testSuite, Failure failure)
+ {
+ Element errorElt = testsuitesDocument.createElement(XMLConstants.ERROR);
+ errorElt.setAttribute(XMLConstants.ATTR_TYPE, failure.getType().name());
+ errorElt.setAttribute(XMLConstants.ATTR_MESSAGE, failure.getMessage());
+
errorElt.appendChild(testsuitesDocument.createCDATASection(stackToString(failure.getStackTrace())));
+
+ //
+ testSuiteListMap.get(testSuite).add(errorElt);
+ }
+
+ protected void startTestSuite(TestSuite testSuite)
+ {
+ List<Element> elements = new ArrayList<Element>();
+ testSuiteListMap.put(testSuite, elements);
+ }
+
+ protected void endTestSuite(TestSuite testSuite)
+ {
+ StringBuffer fqn = testSuite.getFQN();
+
+ List<Element> elements = testSuiteListMap.remove(testSuite);
+
+ //
+ if( testSuite.startedTests.size() > 0 )
+ {
+ for(TestId id : testSuite.startedTests.keySet())
+ {
+ Element errorNotEnded =
testsuitesDocument.createElement(XMLConstants.ERROR);
+ errorNotEnded.setAttribute(XMLConstants.ATTR_MESSAGE, "Testcase: "
+ id + " was not ended properly. (No EndTestEvent)");
+ elements.add(errorNotEnded);
+ }
+ }
+
+ //
+ int pos = fqn.lastIndexOf(".");
+ String packageName = (pos == -1) ? "" : fqn.substring(0, pos);
+ String className = (pos == -1) ? fqn.toString() : fqn.substring(pos + 1);
+
+ //
+ StringWriter out = new StringWriter();
+ StringWriter err = new StringWriter();
+ try
+ {
+ testSuite.view.writeTo(out, err);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+
+ Element systemError = testsuitesDocument.createElement(XMLConstants.SYSTEM_ERR);
+ systemError.appendChild(testsuitesDocument.createCDATASection(err.toString()));
+ Element systemOutElement =
testsuitesDocument.createElement(XMLConstants.SYSTEM_OUT);
+
systemOutElement.appendChild(testsuitesDocument.createCDATASection(out.toString()));
+
+ //
+ Element testSuiteElt = testsuitesDocument.createElement(XMLConstants.TESTSUITE);
+
+ //
+ testSuiteElt.setAttribute(XMLConstants.TIMESTAMP, createTimestamp());
+ testSuiteElt.setAttribute(XMLConstants.HOSTNAME, getHostName());
+ testSuiteElt.setAttribute(XMLConstants.ATTR_PACKAGE, packageName);
+ testSuiteElt.setAttribute(XMLConstants.ATTR_NAME, className);
+ testSuiteElt.setAttribute(XMLConstants.ATTR_TESTS,
Integer.toString(testSuite.tests));
+ testSuiteElt.setAttribute(XMLConstants.ATTR_ERRORS,
Integer.toString(testSuite.errors));
+ testSuiteElt.setAttribute(XMLConstants.ATTR_FAILURES,
Integer.toString(testSuite.failed));
+ testSuiteElt.setAttribute(XMLConstants.ATTR_TIME,
DURATION_FORMAT.format(testSuite.durationMillis / 1000.0));
+
+ //
+ for (Element elt : elements)
+ {
+ testSuiteElt.appendChild(elt);
+ }
+
+ //
+
testSuiteElt.appendChild(testsuitesDocument.createElement(XMLConstants.PROPERTIES));
+ testSuiteElt.appendChild(systemError);
+ testSuiteElt.appendChild(systemOutElement);
+
+ //
+ if (xmlReportDir != null)
+ {
+ Document tmp = createDocument();
+ Element copy = (Element)tmp.importNode(testSuiteElt, true);
+ tmp.appendChild(copy);
+ String a = copy.getAttribute("package");
+ String b = copy.getAttribute("name");
+ String c = a.length() == 0 ? b : a + "." + b;
+ copy.setAttribute("name", c);
+ copy.removeAttribute("package");
+ try
+ {
+ Integer counter = fileNameCounters.get(c);
+ if (counter == null)
+ {
+ counter = 0;
+ }
+ else
+ {
+ counter = counter + 1;
+ }
+ fileNameCounters.put(c, counter);
+ File f = new File(xmlReportDir, TEST_FILE_NAME_PREFIX + c + (counter == 0 ?
"" : "_" + counter) + ".xml");
+ if (!f.exists())
+ {
+ f.createNewFile();
+ }
+ dump(tmp, f);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ //
+ testsuitesElement.appendChild(testSuiteElt);
+ }
+
+ private void dump(Node node, File dest)
+ {
+ try
+ {
+ Source source = new DOMSource(node);
+ Transformer xtrans = TransformerFactory.newInstance().newTransformer();
+ xtrans.setOutputProperty(OutputKeys.INDENT, "yes");
+ xtrans.setOutputProperty(OutputKeys.METHOD, "xml");
+ xtrans.setOutputProperty(OutputKeys.STANDALONE, "yes");
+ Result result = new StreamResult(dest);
+ xtrans.transform(source, result);
+ }
+ catch (TransformerException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ protected void endTestCase(TestSuite testSuite, String testName, TestResult result)
+ {
+ Element test = testsuitesDocument.createElement(XMLConstants.TESTCASE);
+ test.setAttribute(XMLConstants.ATTR_CLASSNAME, testSuite.getFQN().toString());
+ test.setAttribute(XMLConstants.ATTR_NAME, testName);
+ test.setAttribute(XMLConstants.ATTR_TIME,
DURATION_FORMAT.format(result.getDurationMillis() / 1000.0));
+
+ /** If testcase failed */
+ if (result instanceof TestFailure)
+ {
+ TestFailure testFailure = (TestFailure) result;
+ Failure failure = testFailure.getFailure();
+
+ String failureType;
+ // Check failure type (failed, error)
+ if(FailureType.ASSERTION == failure.getType())
+ {
+ testSuite.failed++;
+ failureType = XMLConstants.FAILURE;
+ }
+ else
+ {
+ testSuite.errors++;
+ failureType = XMLConstants.ERROR;
+ }
+
+ test.appendChild(addError(failureType, failure.getStackTrace()));
+ }
+
+ //
+ testSuiteListMap.get(testSuite).add(test);
+
+
+ //
+// if (info != null)
+// {
+//
+//
+// }
+// else
+// {
+// // If test is not started - add error message
+// Element errorNotStarted = document.createElement(XMLConstants.ERROR);
+// errorNotStarted.setAttribute(XMLConstants.ATTR_MESSAGE, "TestCase: "
+ testId + " was not started properly. (No StartTestEvent)");
+// test.appendChild(errorNotStarted);
+// }
+ }
+
+
+ private Element addError(String type, Throwable t)
+ {
+ Element error = testsuitesDocument.createElement(type);
+
+ // Testcase error message
+ error.setAttribute(XMLConstants.ATTR_MESSAGE, t.getMessage());
+
+ // Testcase error type
+ error.setAttribute(XMLConstants.ATTR_TYPE, t.getClass().getName());
+
+ // Testcase stacktrace
+ error.appendChild(testsuitesDocument.createCDATASection(stackToString(t)));
+
+ //
+ return error;
+ }
+
+ private static String stackToString(Throwable t)
+ {
+ Writer writer = new StringWriter();
+ PrintWriter printWriter = new PrintWriter(writer);
+ t.printStackTrace(printWriter);
+ printWriter.close();
+ return writer.toString();
+ }
+
+ /**
+ * Generates a new timestamp string.
+ *
+ * @return a newly create timestamp string
+ */
+ private static String createTimestamp()
+ {
+ return TIMESTAMP_FORMAT.format(new Date());
+ }
+
+ private static String getHostName()
+ {
+ try
+ {
+ return InetAddress.getLocalHost().getHostName();
+ }
+ catch(UnknownHostException e)
+ {
+ return "localhost";
+ }
+ }
+
+ private static Document createDocument()
+ {
+ try
+ {
+ return DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
+ }
+ catch(ParserConfigurationException e)
+ {
+ throw new Error(e);
+ }
+ }
+}
\ No newline at end of file
Added: modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/StringUtils.java
===================================================================
--- modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/StringUtils.java
(rev 0)
+++
modules/test/trunk/unit/src/main/org/jboss/unit/report/impl/junit/StringUtils.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -0,0 +1,35 @@
+/******************************************************************************
+ * JBoss, a division of Red Hat *
+ * Copyright 2006, Red Hat Middleware, LLC, and individual *
+ * contributors as indicated by the @authors tag. See the *
+ * copyright.txt in the distribution for a full listing of *
+ * individual contributors. *
+ * *
+ * This is free software; you can redistribute it and/or modify it *
+ * under the terms of the GNU Lesser General Public License as *
+ * published by the Free Software Foundation; either version 2.1 of *
+ * the License, or (at your option) any later version. *
+ * *
+ * This software is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this software; if not, write to the Free *
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org. *
+ ******************************************************************************/
+package org.jboss.unit.report.impl.junit;
+
+/**
+ * @author <a href="mailto:julien@jboss.org">Julien Viet</a>
+ * @version $Revision: 1.1 $
+ */
+public class StringUtils
+{
+ public static String replace(String data, String from, String to)
+ {
+ return data.replace(from, to);
+ }
+}
Modified:
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/ByteArrayOutputStreamExt.java
===================================================================
---
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/ByteArrayOutputStreamExt.java 2007-10-21
15:33:41 UTC (rev 8730)
+++
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/ByteArrayOutputStreamExt.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -42,7 +42,7 @@
public int writeTo(Writer out, int from) throws IOException,
ArrayIndexOutOfBoundsException
{
- String s = new String(buf, from, count);
+ String s = new String(buf, from, count - from);
out.write(s);
return count;
}
Modified: modules/test/trunk/unit/src/main/org/jboss/unit/tooling/Main.java
===================================================================
--- modules/test/trunk/unit/src/main/org/jboss/unit/tooling/Main.java 2007-10-21 15:33:41
UTC (rev 8730)
+++ modules/test/trunk/unit/src/main/org/jboss/unit/tooling/Main.java 2007-10-22 10:25:33
UTC (rev 8731)
@@ -165,11 +165,9 @@
this.parameters = parameters;
}
- private SystemOutputManager systemManager;
-
public void execute() throws Exception
{
- systemManager = new SystemOutputManager();
+ SystemOutputManager systemManager = new SystemOutputManager();
systemManager.start();
//
Modified: modules/test/trunk/unit/src/main/org/jboss/unit/tooling/MainBuilder.java
===================================================================
--- modules/test/trunk/unit/src/main/org/jboss/unit/tooling/MainBuilder.java 2007-10-21
15:33:41 UTC (rev 8730)
+++ modules/test/trunk/unit/src/main/org/jboss/unit/tooling/MainBuilder.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -23,6 +23,7 @@
package org.jboss.unit.tooling;
import org.jboss.unit.report.impl.junit.JUnitReporter;
+import org.jboss.unit.report.impl.junit.JUnitTestsuiteReport;
import org.jboss.unit.runner.TestRunner;
import org.jboss.unit.runner.TestRunnerEventListener;
import org.jboss.unit.runner.impl.NullFilter;
@@ -32,7 +33,6 @@
import org.jboss.unit.tooling.filter.ExcludeTestFilter;
import org.jboss.unit.tooling.filter.IncludeTestFilter;
import org.jboss.unit.tooling.filter.MainTestFilter;
-import org.jboss.unit.tooling.report.DelegatingReporter;
import org.xml.sax.InputSource;
import java.io.File;
@@ -40,10 +40,10 @@
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.LinkedList;
/**
* @author <a href="mailto:boleslaw dot dawidowicz at redhat anotherdot
com">Boleslaw Dawidowicz</a>
@@ -499,32 +499,20 @@
//add PrintListener by default
- DelegatingReporter reporter = new DelegatingReporter(noConsole);
-
+ //
+ File htmlReportFile = null;
+ if (htmlReportDir != null)
+ {
+ htmlReportFile = checkCreateOutputDirectory(htmlReportDir);
+ }
+ File xmlReportFile = null;
if (xmlReportDir != null)
{
-
- //XML Output directory must exists
- checkCreateOutputDirectory(xmlReportDir);
-
- JUnitReporter xmlReporter = null;
- if (getSuiteName() != null)
- {
- xmlReporter = new JUnitReporter(xmlReportDir, getSuiteName());
- }
- else
- {
- xmlReporter = new JUnitReporter(xmlReportDir);
- }
-
- reporter.setXmlReporter(xmlReporter);
+ xmlReportFile = checkCreateOutputDirectory(xmlReportDir);
}
+ JUnitTestsuiteReport fileReporter = new JUnitTestsuiteReport(xmlReportFile,
htmlReportFile);
+ broadcaster.addListener(fileReporter);
- broadcaster.addListener(reporter);
-
-
-
-
MainTestFilter filter = new MainTestFilter();
if (keywords.size() == 0 && names.size() == 0 &&
namePatterns.size() == 0)
@@ -545,22 +533,18 @@
filter.addExcludeFilter(new ExcludeTestFilter(excludeKeywords, excludeNames,
excludeNamePatterns));
}
-
return new Main(runner, filter, broadcaster, suite, properties, getParameters());
}
- public static void checkCreateOutputDirectory(String dir) throws Exception
+ public static File checkCreateOutputDirectory(String dir) throws Exception
{
- File output = null;
-
try
{
- output = new File(dir);
+ File output = new File(dir);
- //Check if the dir exits and if not create it
+ // heck if the dir exits and if not create it
if (!output.exists())
{
-
output.mkdirs();
}
else
@@ -571,15 +555,13 @@
}
}
+ //
+ return output;
}
catch (Exception e)
{
throw new IllegalStateException("Failed to use provided output directory:
'" + dir + "'", e);
}
-
}
-
-
-
}
Modified:
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/SystemOutputManager.java
===================================================================
---
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/SystemOutputManager.java 2007-10-21
15:33:41 UTC (rev 8730)
+++
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/SystemOutputManager.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -56,9 +56,9 @@
return instance;
}
- public SystemOutputView createView()
+ public SystemOutputView createView(boolean fullHistory)
{
- return new SystemOutputView(baosOut, baosErr);
+ return new SystemOutputView(baosOut, baosErr, fullHistory);
}
public void start()
Modified: modules/test/trunk/unit/src/main/org/jboss/unit/tooling/SystemOutputView.java
===================================================================
---
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/SystemOutputView.java 2007-10-21
15:33:41 UTC (rev 8730)
+++
modules/test/trunk/unit/src/main/org/jboss/unit/tooling/SystemOutputView.java 2007-10-22
10:25:33 UTC (rev 8731)
@@ -45,12 +45,12 @@
/** . */
private int errCount;
- public SystemOutputView(ByteArrayOutputStreamExt out, ByteArrayOutputStreamExt err)
+ public SystemOutputView(ByteArrayOutputStreamExt out, ByteArrayOutputStreamExt err,
boolean fullHistory)
{
this.out = out;
this.err = err;
- this.outCount = 0;
- this.errCount = 0;
+ this.outCount = fullHistory ? 0 : out.size();
+ this.errCount = fullHistory ? 0 : err.size();
}
public void writeTo(OutputStream toOut, OutputStream toErr) throws IOException
Added:
modules/test/trunk/unit/src/resources/jboss-unit-jar/org/jboss/unit/report/impl/junit/junit-frames.xsl
===================================================================
---
modules/test/trunk/unit/src/resources/jboss-unit-jar/org/jboss/unit/report/impl/junit/junit-frames.xsl
(rev 0)
+++
modules/test/trunk/unit/src/resources/jboss-unit-jar/org/jboss/unit/report/impl/junit/junit-frames.xsl 2007-10-22
10:25:33 UTC (rev 8731)
@@ -0,0 +1,712 @@
+<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0"
+
xmlns:lxslt="http://xml.apache.org/xslt"
+
xmlns:redirect="http://xml.apache.org/xalan/redirect"
+ xmlns:stringutils="org.jboss.unit.report.impl.junit.StringUtils"
+ extension-element-prefixes="redirect">
+<xsl:output method="html" indent="yes"
encoding="US-ASCII"/>
+<xsl:decimal-format decimal-separator="."
grouping-separator=","/>
+<!--
+ Copyright 2001-2005 The Apache Software Foundation
+
+ 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.
+ -->
+
+<!--
+
+ Sample stylesheet to be used with Ant JUnitReport output.
+
+ It creates a set of HTML files a la javadoc where you can browse easily
+ through all packages and classes.
+
+-->
+<xsl:param name="output.dir" select="'.'"/>
+
+
+<xsl:template match="testsuites">
+ <!-- create the index.html -->
+ <redirect:write file="{$output.dir}/index.html">
+ <xsl:call-template name="index.html"/>
+ </redirect:write>
+
+ <!-- create the stylesheet.css -->
+ <redirect:write file="{$output.dir}/stylesheet.css">
+ <xsl:call-template name="stylesheet.css"/>
+ </redirect:write>
+
+ <!-- create the overview-packages.html at the root -->
+ <redirect:write file="{$output.dir}/overview-summary.html">
+ <xsl:apply-templates select="."
mode="overview.packages"/>
+ </redirect:write>
+
+ <!-- create the all-packages.html at the root -->
+ <redirect:write file="{$output.dir}/overview-frame.html">
+ <xsl:apply-templates select="." mode="all.packages"/>
+ </redirect:write>
+
+ <!-- create the all-classes.html at the root -->
+ <redirect:write file="{$output.dir}/allclasses-frame.html">
+ <xsl:apply-templates select="." mode="all.classes"/>
+ </redirect:write>
+
+ <!-- process all packages -->
+ <xsl:for-each select="./testsuite[not(./@package =
preceding-sibling::testsuite/@package)]">
+ <xsl:call-template name="package">
+ <xsl:with-param name="name" select="@package"/>
+ </xsl:call-template>
+ </xsl:for-each>
+</xsl:template>
+
+
+<xsl:template name="package">
+ <xsl:param name="name"/>
+ <xsl:variable name="package.dir">
+ <xsl:if test="not($name = '')"><xsl:value-of
select="translate($name,'.','/')"/></xsl:if>
+ <xsl:if test="$name = ''">.</xsl:if>
+ </xsl:variable>
+ <!--Processing package <xsl:value-of select="@name"/> in
<xsl:value-of select="$output.dir"/> -->
+ <!-- create a classes-list.html in the package directory -->
+ <redirect:write
file="{$output.dir}/{$package.dir}/package-frame.html">
+ <xsl:call-template name="classes.list">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </redirect:write>
+
+ <!-- create a package-summary.html in the package directory -->
+ <redirect:write
file="{$output.dir}/{$package.dir}/package-summary.html">
+ <xsl:call-template name="package.summary">
+ <xsl:with-param name="name" select="$name"/>
+ </xsl:call-template>
+ </redirect:write>
+
+ <!-- for each class, creates a @name.html -->
+ <!-- @bug there will be a problem with inner classes having the same name, it will
be overwritten -->
+ <xsl:for-each select="/testsuites/testsuite[@package = $name]">
+ <redirect:write
file="{$output.dir}/{$package.dir}/{@id}_{(a)name}.html">
+ <xsl:apply-templates select="."
mode="class.details"/>
+ </redirect:write>
+ <xsl:if test="string-length(./system-out)!=0">
+ <redirect:write
file="{$output.dir}/{$package.dir}/{@id}_{(a)name}-out.txt">
+ <xsl:value-of select="./system-out" />
+ </redirect:write>
+ </xsl:if>
+ <xsl:if test="string-length(./system-err)!=0">
+ <redirect:write
file="{$output.dir}/{$package.dir}/{@id}_{(a)name}-err.txt">
+ <xsl:value-of select="./system-err" />
+ </redirect:write>
+ </xsl:if>
+ </xsl:for-each>
+</xsl:template>
+
+<xsl:template name="index.html">
+<html>
+ <head>
+ <title>Unit Test Results.</title>
+ </head>
+ <frameset cols="20%,80%">
+ <frameset rows="30%,70%">
+ <frame src="overview-frame.html"
name="packageListFrame"/>
+ <frame src="allclasses-frame.html"
name="classListFrame"/>
+ </frameset>
+ <frame src="overview-summary.html" name="classFrame"/>
+ <noframes>
+ <h2>Frame Alert</h2>
+ <p>
+ This document is designed to be viewed using the frames feature. If you
see this message, you are using a non-frame-capable web client.
+ </p>
+ </noframes>
+ </frameset>
+</html>
+</xsl:template>
+
+<!-- this is the stylesheet css to use for nearly everything -->
+<xsl:template name="stylesheet.css">
+body {
+ font:normal 68% verdana,arial,helvetica;
+ color:#000000;
+}
+table tr td, table tr th {
+ font-size: 68%;
+}
+table.details tr th{
+ font-weight: bold;
+ text-align:left;
+ background:#a6caf0;
+}
+table.details tr td{
+ background:#eeeee0;
+}
+
+p {
+ line-height:1.5em;
+ margin-top:0.5em; margin-bottom:1.0em;
+}
+h1 {
+ margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
+}
+h2 {
+ margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
+}
+h3 {
+ margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
+}
+h4 {
+ margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
+}
+h5 {
+ margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
+}
+h6 {
+ margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
+}
+.Error {
+ font-weight:bold; color:red;
+}
+.Failure {
+ font-weight:bold; color:purple;
+}
+.Properties {
+ text-align:right;
+}
+</xsl:template>
+
+
+<!-- ======================================================================
+ This page is created for every testsuite class.
+ It prints a summary of the testsuite and detailed information about
+ testcase methods.
+ ====================================================================== -->
+<xsl:template match="testsuite" mode="class.details">
+ <xsl:variable name="package.name" select="@package"/>
+ <xsl:variable name="class.name"><xsl:if
test="not($package.name = '')"><xsl:value-of
select="$package.name"/>.</xsl:if><xsl:value-of
select="@name"/></xsl:variable>
+ <html>
+ <head>
+ <title>Unit Test Results: <xsl:value-of
select="$class.name"/></title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name"
select="$package.name"/>
+ </xsl:call-template>
+ <script type="text/javascript" language="JavaScript">
+ var TestCases = new Array();
+ var cur;
+ <xsl:apply-templates select="properties"/>
+ </script>
+ <script type="text/javascript"
language="JavaScript"><![CDATA[
+ function displayProperties (name) {
+ var win =
window.open('','JUnitSystemProperties','scrollbars=1,resizable=1');
+ var doc = win.document.open();
+ doc.write("<html><head><title>Properties of " +
name + "</title>");
+ doc.write("<style type=\"text/css\">");
+ doc.write("body {font:normal 68% verdana,arial,helvetica; color:#000000;
}");
+ doc.write("table tr td, table tr th { font-size: 68%; }");
+ doc.write("table.properties { border-collapse:collapse; border-left:solid
1 #cccccc; border-top:solid 1 #cccccc; padding:5px; }");
+ doc.write("table.properties th { text-align:left; border-right:solid 1
#cccccc; border-bottom:solid 1 #cccccc; background-color:#eeeeee; }");
+ doc.write("table.properties td { font:normal; text-align:left;
border-right:solid 1 #cccccc; border-bottom:solid 1 #cccccc; background-color:#fffffff;
}");
+ doc.write("h3 { margin-bottom: 0.5em; font: bold 115%
verdana,arial,helvetica }");
+ doc.write("</style>");
+ doc.write("</head><body>");
+ doc.write("<h3>Properties of " + name +
"</h3>");
+ doc.write("<div align=\"right\"><a
href=\"javascript:window.close();\">Close</a></div>");
+ doc.write("<table class='properties'>");
+
doc.write("<tr><th>Name</th><th>Value</th></tr>");
+ for (prop in TestCases[name]) {
+ doc.write("<tr><th>" + prop +
"</th><td>" + TestCases[name][prop] +
"</td></tr>");
+ }
+ doc.write("</table>");
+ doc.write("</body></html>");
+ doc.close();
+ win.focus();
+ }
+ ]]>
+ </script>
+ </head>
+ <body>
+ <xsl:call-template name="pageHeader"/>
+ <h3>Class <xsl:value-of
select="$class.name"/></h3>
+
+
+ <table class="details" border="0"
cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testsuite.test.header"/>
+ <xsl:apply-templates select="."
mode="print.test"/>
+ </table>
+
+ <h2>Tests</h2>
+ <table class="details" border="0"
cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testcase.test.header"/>
+ <!--
+ test can even not be started at all (failure to load the class)
+ so report the error directly
+ -->
+ <xsl:if test="./error">
+ <tr class="Error">
+ <td colspan="4"><xsl:apply-templates
select="./error"/></td>
+ </tr>
+ </xsl:if>
+ <xsl:apply-templates select="./testcase"
mode="print.test"/>
+ </table>
+ <div class="Properties">
+ <a>
+ <xsl:attribute
name="href">javascript:displayProperties('<xsl:value-of
select="@package"/>.<xsl:value-of
select="@name"/>');</xsl:attribute>
+ Properties »
+ </a>
+ </div>
+ <xsl:if test="string-length(./system-out)!=0">
+ <div class="Properties">
+ <a>
+ <xsl:attribute name="href">./<xsl:value-of
select="@id"/>_<xsl:value-of
select="@name"/>-out.txt</xsl:attribute>
+ System.out »
+ </a>
+ </div>
+ </xsl:if>
+ <xsl:if test="string-length(./system-err)!=0">
+ <div class="Properties">
+ <a>
+ <xsl:attribute name="href">./<xsl:value-of
select="@id"/>_<xsl:value-of
select="@name"/>-err.txt</xsl:attribute>
+ System.err »
+ </a>
+ </div>
+ </xsl:if>
+ </body>
+ </html>
+</xsl:template>
+
+ <!--
+ Write properties into a JavaScript data structure.
+ This is based on the original idea by Erik Hatcher (ehatcher(a)apache.org)
+ -->
+ <xsl:template match="properties">
+ cur = TestCases['<xsl:value-of
select="../@package"/>.<xsl:value-of
select="../@name"/>'] = new Array();
+ <xsl:for-each select="property">
+ <xsl:sort select="@name"/>
+ cur['<xsl:value-of select="@name"/>'] =
'<xsl:call-template name="JS-escape"><xsl:with-param
name="string" select="@value"/></xsl:call-template>';
+ </xsl:for-each>
+ </xsl:template>
+
+
+<!-- ======================================================================
+ This page is created for every package.
+ It prints the name of all classes that belongs to this package.
+ @param name the package name to print classes.
+ ====================================================================== -->
+<!-- list of classes in a package -->
+<xsl:template name="classes.list">
+ <xsl:param name="name"/>
+ <html>
+ <head>
+ <title>Unit Test Classes: <xsl:value-of
select="$name"/></title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name"
select="$name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <table width="100%">
+ <tr>
+ <td nowrap="nowrap">
+ <h2><a href="package-summary.html"
target="classFrame">
+ <xsl:value-of select="$name"/>
+ <xsl:if test="$name =
''"><none></xsl:if>
+ </a></h2>
+ </td>
+ </tr>
+ </table>
+
+ <h2>Classes</h2>
+ <table width="100%">
+ <xsl:for-each select="/testsuites/testsuite[./@package =
$name]">
+ <xsl:sort select="@name"/>
+ <tr>
+ <td nowrap="nowrap">
+ <a href="{@id}_{(a)name}.html"
target="classFrame"><xsl:value-of select="@name"/></a>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+
+
+<!--
+ Creates an all-classes.html file that contains a link to all package-summary.html
+ on each class.
+-->
+<xsl:template match="testsuites" mode="all.classes">
+ <html>
+ <head>
+ <title>All Unit Test Classes</title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <h2>Classes</h2>
+ <table width="100%">
+ <xsl:apply-templates select="testsuite"
mode="all.classes">
+ <xsl:sort select="@name"/>
+ </xsl:apply-templates>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+
+<xsl:template match="testsuite" mode="all.classes">
+ <xsl:variable name="package.name" select="@package"/>
+ <tr>
+ <td nowrap="nowrap">
+ <a target="classFrame">
+ <xsl:attribute name="href">
+ <xsl:if test="not($package.name='')">
+ <xsl:value-of
select="translate($package.name,'.','/')"/><xsl:text>/</xsl:text>
+ </xsl:if><xsl:value-of
select="@id"/>_<xsl:value-of
select="@name"/><xsl:text>.html</xsl:text>
+ </xsl:attribute>
+ <xsl:value-of select="@name"/>
+ </a>
+ </td>
+ </tr>
+</xsl:template>
+
+
+<!--
+ Creates an html file that contains a link to all package-summary.html files on
+ each package existing on testsuites.
+ @bug there will be a problem here, I don't know yet how to handle unnamed package
:(
+-->
+<xsl:template match="testsuites" mode="all.packages">
+ <html>
+ <head>
+ <title>All Unit Test Packages</title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <h2><a href="overview-summary.html"
target="classFrame">Home</a></h2>
+ <h2>Packages</h2>
+ <table width="100%">
+ <xsl:apply-templates select="testsuite[not(./@package =
preceding-sibling::testsuite/@package)]" mode="all.packages">
+ <xsl:sort select="@package"/>
+ </xsl:apply-templates>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+
+<xsl:template match="testsuite" mode="all.packages">
+ <tr>
+ <td nowrap="nowrap">
+ <a
href="./{translate((a)package,'.','/')}/package-summary.html"
target="classFrame">
+ <xsl:value-of select="@package"/>
+ <xsl:if test="@package =
''"><none></xsl:if>
+ </a>
+ </td>
+ </tr>
+</xsl:template>
+
+
+<xsl:template match="testsuites" mode="overview.packages">
+ <html>
+ <head>
+ <title>Unit Test Results: Summary</title>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <xsl:attribute
name="onload">open('allclasses-frame.html','classListFrame')</xsl:attribute>
+ <xsl:call-template name="pageHeader"/>
+ <h2>Summary</h2>
+ <xsl:variable name="testCount"
select="sum(testsuite/@tests)"/>
+ <xsl:variable name="errorCount"
select="sum(testsuite/@errors)"/>
+ <xsl:variable name="failureCount"
select="sum(testsuite/@failures)"/>
+ <xsl:variable name="timeCount"
select="sum(testsuite/@time)"/>
+ <xsl:variable name="successRate" select="($testCount -
$failureCount - $errorCount) div $testCount"/>
+ <table class="details" border="0"
cellpadding="5" cellspacing="2" width="95%">
+ <tr valign="top">
+ <th>Tests</th>
+ <th>Failures</th>
+ <th>Errors</th>
+ <th>Success rate</th>
+ <th>Time</th>
+ </tr>
+ <tr valign="top">
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="$errorCount >
0">Error</xsl:when>
+ <xsl:when test="$failureCount >
0">Failure</xsl:when>
+ <xsl:otherwise>Pass</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><xsl:value-of select="$testCount"/></td>
+ <td><xsl:value-of select="$failureCount"/></td>
+ <td><xsl:value-of select="$errorCount"/></td>
+ <td>
+ <xsl:call-template name="display-percent">
+ <xsl:with-param name="value"
select="$successRate"/>
+ </xsl:call-template>
+ </td>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value"
select="$timeCount"/>
+ </xsl:call-template>
+ </td>
+
+ </tr>
+ </table>
+ <table border="0" width="95%">
+ <tr>
+ <td style="text-align: justify;">
+ Note: <em>failures</em> are anticipated and checked for with
assertions while <em>errors</em> are unanticipated.
+ </td>
+ </tr>
+ </table>
+
+ <h2>Packages</h2>
+ <table class="details" border="0"
cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testsuite.test.header"/>
+ <xsl:for-each select="testsuite[not(./@package =
preceding-sibling::testsuite/@package)]">
+ <xsl:sort select="@package"
order="ascending"/>
+ <!-- get the node set containing all testsuites that have the same
package -->
+ <xsl:variable name="insamepackage"
select="/testsuites/testsuite[./@package = current()/@package]"/>
+ <tr valign="top">
+ <!-- display a failure if there is any failure/error in the
package -->
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="sum($insamepackage/@errors) >
0">Error</xsl:when>
+ <xsl:when test="sum($insamepackage/@failures)
> 0">Failure</xsl:when>
+ <xsl:otherwise>Pass</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><a
href="./{translate((a)package,'.','/')}/package-summary.html">
+ <xsl:value-of select="@package"/>
+ <xsl:if test="@package =
''"><none></xsl:if>
+ </a></td>
+ <td><xsl:value-of
select="sum($insamepackage/@tests)"/></td>
+ <td><xsl:value-of
select="sum($insamepackage/@errors)"/></td>
+ <td><xsl:value-of
select="sum($insamepackage/@failures)"/></td>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value"
select="sum($insamepackage/@time)"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </table>
+ </body>
+ </html>
+</xsl:template>
+
+
+<xsl:template name="package.summary">
+ <xsl:param name="name"/>
+ <html>
+ <head>
+ <xsl:call-template name="create.stylesheet.link">
+ <xsl:with-param name="package.name"
select="$name"/>
+ </xsl:call-template>
+ </head>
+ <body>
+ <xsl:attribute
name="onload">open('package-frame.html','classListFrame')</xsl:attribute>
+ <xsl:call-template name="pageHeader"/>
+ <h3>Package <xsl:value-of select="$name"/></h3>
+
+ <!--table border="0" cellpadding="5"
cellspacing="2" width="95%">
+ <xsl:call-template name="class.metrics.header"/>
+ <xsl:apply-templates select="."
mode="print.metrics"/>
+ </table-->
+
+ <xsl:variable name="insamepackage"
select="/testsuites/testsuite[./@package = $name]"/>
+ <xsl:if test="count($insamepackage) > 0">
+ <h2>Classes</h2>
+ <p>
+ <table class="details" border="0"
cellpadding="5" cellspacing="2" width="95%">
+ <xsl:call-template name="testsuite.test.header"/>
+ <xsl:apply-templates select="$insamepackage"
mode="print.test">
+ <xsl:sort select="@name"/>
+ </xsl:apply-templates>
+ </table>
+ </p>
+ </xsl:if>
+ </body>
+ </html>
+</xsl:template>
+
+
+<!--
+ transform string like a.b.c to ../../../
+ @param path the path to transform into a descending directory path
+-->
+<xsl:template name="path">
+ <xsl:param name="path"/>
+ <xsl:if test="contains($path,'.')">
+ <xsl:text>../</xsl:text>
+ <xsl:call-template name="path">
+ <xsl:with-param name="path"><xsl:value-of
select="substring-after($path,'.')"/></xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not(contains($path,'.')) and not($path =
'')">
+ <xsl:text>../</xsl:text>
+ </xsl:if>
+</xsl:template>
+
+
+<!-- create the link to the stylesheet based on the package name -->
+<xsl:template name="create.stylesheet.link">
+ <xsl:param name="package.name"/>
+ <link rel="stylesheet" type="text/css"
title="Style"><xsl:attribute name="href"><xsl:if
test="not($package.name = 'unnamed package')"><xsl:call-template
name="path"><xsl:with-param name="path"
select="$package.name"/></xsl:call-template></xsl:if>stylesheet.css</xsl:attribute></link>
+</xsl:template>
+
+
+<!-- Page HEADER -->
+<xsl:template name="pageHeader">
+ <h1>Unit Test Results</h1>
+ <table width="100%">
+ <tr>
+ <td align="left"></td>
+ <td align="right">Designed for use with <a
href="http://www.junit.org/">JUnit</a> and <a
href="http://jakarta.apache.org/">Ant</a>.</td>
+ </tr>
+ </table>
+ <hr size="1"/>
+</xsl:template>
+
+<!-- class header -->
+<xsl:template name="testsuite.test.header">
+ <tr valign="top">
+ <th width="80%">Name</th>
+ <th>Tests</th>
+ <th>Errors</th>
+ <th>Failures</th>
+ <th nowrap="nowrap">Time(s)</th>
+ </tr>
+</xsl:template>
+
+<!-- method header -->
+<xsl:template name="testcase.test.header">
+ <tr valign="top">
+ <th>Name</th>
+ <th>Status</th>
+ <th width="80%">Type</th>
+ <th nowrap="nowrap">Time(s)</th>
+ </tr>
+</xsl:template>
+
+
+<!-- class information -->
+<xsl:template match="testsuite" mode="print.test">
+ <tr valign="top">
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="(a)errors[.&gt;
0]">Error</xsl:when>
+ <xsl:when test="(a)failures[.&gt;
0]">Failure</xsl:when>
+ <xsl:otherwise>Pass</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><a href="{@id}_{@name}.html"><xsl:value-of
select="@name"/></a></td>
+ <td><xsl:apply-templates select="@tests"/></td>
+ <td><xsl:apply-templates select="@errors"/></td>
+ <td><xsl:apply-templates select="@failures"/></td>
+ <td><xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="@time"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+</xsl:template>
+
+<xsl:template match="testcase" mode="print.test">
+ <tr valign="top">
+ <xsl:attribute name="class">
+ <xsl:choose>
+ <xsl:when test="error">Error</xsl:when>
+ <xsl:when test="failure">Failure</xsl:when>
+ <xsl:otherwise>TableRowColor</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <td><xsl:value-of select="@name"/></td>
+ <xsl:choose>
+ <xsl:when test="failure">
+ <td>Failure</td>
+ <td><xsl:apply-templates
select="failure"/></td>
+ </xsl:when>
+ <xsl:when test="error">
+ <td>Error</td>
+ <td><xsl:apply-templates
select="error"/></td>
+ </xsl:when>
+ <xsl:otherwise>
+ <td>Success</td>
+ <td></td>
+ </xsl:otherwise>
+ </xsl:choose>
+ <td>
+ <xsl:call-template name="display-time">
+ <xsl:with-param name="value" select="@time"/>
+ </xsl:call-template>
+ </td>
+ </tr>
+</xsl:template>
+
+
+<!-- Note : the below template error and failure are the same style
+ so just call the same style store in the toolkit template -->
+<xsl:template match="failure">
+ <xsl:call-template name="display-failures"/>
+</xsl:template>
+
+<xsl:template match="error">
+ <xsl:call-template name="display-failures"/>
+</xsl:template>
+
+<!-- Style for the error and failure in the testcase template -->
+<xsl:template name="display-failures">
+ <xsl:choose>
+ <xsl:when test="not(@message)">N/A</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@message"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- display the stacktrace -->
+ <br/><br/>
+ <code>
+ <xsl:call-template name="br-replace">
+ <xsl:with-param name="word" select="."/>
+ </xsl:call-template>
+ </code>
+ <!-- the latter is better but might be problematic for non-21" monitors...
-->
+ <!--pre><xsl:value-of select="."/></pre-->
+</xsl:template>
+
+<xsl:template name="JS-escape">
+ <xsl:param name="string"/>
+ <xsl:param name="tmp1"
select="stringutils:replace(string($string),'\','\\')"/>
+ <xsl:param name="tmp2"
select="stringutils:replace(string($tmp1),"'","\'")"/>
+ <xsl:value-of select="$tmp2"/>
+</xsl:template>
+
+
+<!--
+ template that will convert a carriage return into a br tag
+ @param word the text from which to convert CR to BR tag
+-->
+<xsl:template name="br-replace">
+ <xsl:param name="word"/>
+ <xsl:param name="br"><br/></xsl:param>
+ <xsl:value-of
select='stringutils:replace(string($word),"
",$br)'/>
+</xsl:template>
+
+<xsl:template name="display-time">
+ <xsl:param name="value"/>
+ <xsl:value-of select="format-number($value,'0.000')"/>
+</xsl:template>
+
+<xsl:template name="display-percent">
+ <xsl:param name="value"/>
+ <xsl:value-of select="format-number($value,'0.00%')"/>
+</xsl:template>
+</xsl:stylesheet>
+