diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/junit-runner/CommandLine.java | 3 | ||||
-rw-r--r-- | tests/junit-runner/JunitLikeXmlOutputListener.java | 225 | ||||
-rw-r--r-- | tests/report-styles/index.html.in | 25 | ||||
-rw-r--r-- | tests/report-styles/index.js | 67 | ||||
-rw-r--r-- | tests/report-styles/jreport.xsl | 215 | ||||
-rw-r--r-- | tests/report-styles/report.css | 21 |
6 files changed, 556 insertions, 0 deletions
diff --git a/tests/junit-runner/CommandLine.java b/tests/junit-runner/CommandLine.java index ad7dc7e..1807c65 100644 --- a/tests/junit-runner/CommandLine.java +++ b/tests/junit-runner/CommandLine.java @@ -7,6 +7,7 @@ * http://www.eclipse.org/legal/cpl-v10.html */ +import java.io.File; import java.util.ArrayList; import java.util.List; @@ -41,6 +42,8 @@ public class CommandLine extends JUnitCore { system.out().println("ERROR: Could not find class: " + each); } } + RunListener jXmlOutput = new JunitLikeXmlOutputListener(system, new File("tests-output.xml")); + addListener(jXmlOutput); RunListener listener = new LessVerboseTextListener(system); addListener(listener); Result result = run(classes.toArray(new Class[0])); diff --git a/tests/junit-runner/JunitLikeXmlOutputListener.java b/tests/junit-runner/JunitLikeXmlOutputListener.java new file mode 100644 index 0000000..34efc64 --- /dev/null +++ b/tests/junit-runner/JunitLikeXmlOutputListener.java @@ -0,0 +1,225 @@ +/* + * Copyright 2011 Red Hat, Inc. + * + * This file is made available under the terms of the Common Public License + * v1.0 which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + */ + +import java.io.BufferedWriter; +import java.io.File; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.text.DecimalFormat; +import java.text.NumberFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + + +import org.junit.internal.JUnitSystem; +import org.junit.runner.Description; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; +import org.junit.runner.notification.RunListener; +/** + * This class listens for events in junit testsuite and wrote output to xml. + * Xml tryes to follow ant-tests schema, and is enriched for by-class statistics + * stdout and err elements are added, but must be filled from elsewhere (eg tee + * in make) as junit suite and listener run from our executer have no access to + * them. + * + */ +public class JunitLikeXmlOutputListener extends RunListener { + + private BufferedWriter writer; + private Failure testFailed = null; + private static final String ROOT = "testsuite"; + private static final String DATE_ELEMENT = "date"; + private static final String TEST_ELEMENT = "testcase"; + private static final String TEST_NAME_ATTRIBUTE = "name"; + private static final String TEST_TIME_ATTRIBUTE = "time"; + private static final String TEST_ERROR_ELEMENT = "error"; + private static final String TEST_CLASS_ATTRIBUTE = "classname"; + private static final String ERROR_MESSAGE_ATTRIBUTE = "message"; + private static final String ERROR_TYPE_ATTRIBUTE = "type"; + private static final String SOUT_ELEMENT = "system-out"; + private static final String SERR_ELEMENT = "system-err"; + private static final String CDATA_START = "<![CDATA["; + private static final String CDATA_END = "]]>"; + private static final String TEST_CLASS_ELEMENT = "class"; + private static final String STATS_ELEMENT = "stats"; + private static final String CLASSES_ELEMENT = "classes"; + private static final String SUMMARY_ELEMENT = "summary"; + private static final String SUMMARY_TOTAL_ELEMENT = "total"; + private static final String SUMMARY_PASSED_ELEMENT = "passed"; + private static final String SUMMARY_FAILED_ELEMENT = "failed"; + private static final String SUMMARY_IGNORED_ELEMENT = "ignored"; + private long testStart; + + private class ClassCounter { + + int total; + int failed; + int passed; + long time = 0; + } + Map<String, ClassCounter> classStats = new HashMap<String, ClassCounter>(); + + public JunitLikeXmlOutputListener(JUnitSystem system, File f) { + try { + writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(f), "UTF-8")); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } + + @Override + public void testRunStarted(Description description) throws Exception { + openElement(ROOT); + writeElement(DATE_ELEMENT, new Date().toString()); + } + + private void openElement(String name) throws IOException { + openElement(name, null); + } + + private void openElement(String name, Map<String, String> atts) throws IOException { + StringBuilder attString = new StringBuilder(); + if (atts != null) { + attString.append(" "); + Set<Entry<String, String>> entries = atts.entrySet(); + for (Entry<String, String> entry : entries) { + attString.append(entry.getKey()).append("=\"").append(attributize(entry.getValue())).append("\""); + attString.append(" "); + } + } + writer.write("<" + name + attString.toString() + ">"); + writer.newLine(); + } + + private static String attributize(String s) { + return s.replace("&", "&").replace("<", "<"); + } + + private void closeElement(String name) throws IOException { + writer.newLine(); + writer.write("</" + name + ">"); + writer.newLine(); + } + + private void writeContent(String content) throws IOException { + writer.write(CDATA_START + content + CDATA_END); + } + + private void writeElement(String name, String content) throws IOException { + writeElement(name, content, null); + } + + private void writeElement(String name, String content, Map<String, String> atts) throws IOException { + openElement(name, atts); + writeContent(content); + closeElement(name); + } + + @Override + public void testStarted(Description description) throws Exception { + testFailed = null; + testStart = System.nanoTime()/1000l/1000l; + } + + @Override + public void testFailure(Failure failure) throws IOException { + testFailed = failure; + } + + @Override + public void testFinished(org.junit.runner.Description description) throws Exception { + long testTime = System.nanoTime()/1000l/1000l - testStart; + double testTimeSeconds = ((double) testTime) / 1000d; + + Map<String, String> testcaseAtts = new HashMap<String, String>(3); + NumberFormat formatter = new DecimalFormat("#0.0000"); + String stringedTime = formatter.format(testTimeSeconds); + stringedTime.replace(",", "."); + testcaseAtts.put(TEST_TIME_ATTRIBUTE, stringedTime); + testcaseAtts.put(TEST_CLASS_ATTRIBUTE, description.getClassName()); + testcaseAtts.put(TEST_NAME_ATTRIBUTE, description.getMethodName()); + + openElement(TEST_ELEMENT, testcaseAtts); + if (testFailed != null) { + Map<String, String> errorAtts = new HashMap<String, String>(3); + + errorAtts.put(ERROR_MESSAGE_ATTRIBUTE, testFailed.getMessage()); + int i = testFailed.getTrace().indexOf(":"); + if (i >= 0) { + errorAtts.put(ERROR_TYPE_ATTRIBUTE, testFailed.getTrace().substring(0, i)); + } else { + errorAtts.put(ERROR_TYPE_ATTRIBUTE, "?"); + } + + writeElement(TEST_ERROR_ELEMENT, testFailed.getTrace(), errorAtts); + } + + closeElement(TEST_ELEMENT); + writer.flush(); + + ClassCounter cc = classStats.get(description.getClassName()); + if (cc == null) { + cc = new ClassCounter(); + classStats.put(description.getClassName(), cc); + } + cc.total++; + cc.time += testTime; + if (testFailed == null) { + cc.passed++; + } else { + + cc.failed++; + } + } + + @Override + public void testRunFinished(Result result) throws Exception { + + writeElement(SOUT_ELEMENT, "@sout@"); + writeElement(SERR_ELEMENT, "@serr@"); + openElement(STATS_ELEMENT); + openElement(SUMMARY_ELEMENT); + int passed = result.getRunCount() - result.getFailureCount() - result.getIgnoreCount(); + int failed = result.getFailureCount(); + int ignored = result.getIgnoreCount(); + writeElement(SUMMARY_TOTAL_ELEMENT, String.valueOf(result.getRunCount())); + writeElement(SUMMARY_FAILED_ELEMENT, String.valueOf(failed)); + writeElement(SUMMARY_IGNORED_ELEMENT, String.valueOf(ignored)); + writeElement(SUMMARY_PASSED_ELEMENT, String.valueOf(passed)); + closeElement(SUMMARY_ELEMENT); + openElement(CLASSES_ELEMENT); + Set<Entry<String, ClassCounter>> e = classStats.entrySet(); + for (Entry<String, ClassCounter> entry : e) { + + Map<String, String> testcaseAtts = new HashMap<String, String>(3); + testcaseAtts.put(TEST_NAME_ATTRIBUTE, entry.getKey()); + testcaseAtts.put(TEST_TIME_ATTRIBUTE, String.valueOf(entry.getValue().time)); + + openElement(TEST_CLASS_ELEMENT, testcaseAtts); + writeElement(SUMMARY_PASSED_ELEMENT, String.valueOf(entry.getValue().passed)); + writeElement(SUMMARY_FAILED_ELEMENT, String.valueOf(entry.getValue().failed)); + writeElement(SUMMARY_IGNORED_ELEMENT, String.valueOf(entry.getValue().total - entry.getValue().failed - entry.getValue().passed)); + writeElement(SUMMARY_TOTAL_ELEMENT, String.valueOf(entry.getValue().total)); + + closeElement(TEST_CLASS_ELEMENT); + } + closeElement(CLASSES_ELEMENT); + closeElement(STATS_ELEMENT); + + closeElement(ROOT); + writer.flush(); + writer.close(); + + } +} diff --git a/tests/report-styles/index.html.in b/tests/report-styles/index.html.in new file mode 100644 index 0000000..e442602 --- /dev/null +++ b/tests/report-styles/index.html.in @@ -0,0 +1,25 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> + <script src="@xslt_script@"> + </script> + <link href="@css_styles@" rel="stylesheet" type="text/css"/> + </head> + <body onload="xslt('@sheet_path_unit@','@data_path_unit@','wholePage2'); + xslt('@sheet_path_dist@','@data_path_dist@','wholePage4'); + "> + +<div> +<hr/> +<a name="JunitTests">Unit-tests:</a> [<a href="#JdistTests">dist tests</a>] +<hr/> + <div id="wholePage2"/> +</div> + +<hr/> +<a name="JdistTests">Dist-tests:</a> [<a href="#JunitTests">unit tests</a>] +<hr/> + <div id="wholePage4"/> +</div> + </body> +</html> diff --git a/tests/report-styles/index.js b/tests/report-styles/index.js new file mode 100644 index 0000000..51093d1 --- /dev/null +++ b/tests/report-styles/index.js @@ -0,0 +1,67 @@ + +if(typeof String.prototype.trim !== 'function') { String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g, ''); } } + + +function negateIdDisplay(which){ + var e = document.getElementById(which); + if (e.style.display=="block") { + e.style.display="none" + }else{ + e.style.display="block" + } + } + + + function setClassDisplay(which,what) { + var e = document.getElementsByClassName(which); + for ( var i = 0; i < e.length; i++ ){ + e[i].style.display=what + } + } + + + function loadXMLDoc(dname) { + if (window.XMLHttpRequest) { + xhttp=new XMLHttpRequest(); + }else{ + xhttp=new ActiveXObject("Microsoft.XMLHTTP"); + } + xhttp.open("GET",dname,false); + xhttp.send(""); + return xhttp.responseXML; + } + + + function xslt(sheet,data,dest) { + var sheetName=sheet; + var xmlName=data; + var htmlDest=dest; + // code for IE + if (window.ActiveXObject) { + var XML = new ActiveXObject("MSXML2.FreeThreadedDomDocument"); + XML.async = "false"; + XML.load(xmlName); + var XSL = new ActiveXObject("MSXML2.FreeThreadedDomDocument"); + XSL.async = "false"; + XSL.load(sheetName); + var XSLTCompiled = new ActiveXObject("MSXML2.XSLTemplate"); + //Add the stylesheet information + XSLTCompiled.stylesheet = XSL.documentElement; + //Create the XSLT processor + var msSheet = XSLTCompiled.createProcessor(); + msSheet.input = XML + //Perform the transform + msSheet.transform(); + document.getElementById(htmlDest).innerHTML=msSheet.output; + } + // code for Mozilla, Firefox, Opera, etc. + else if (document.implementation && document.implementation.createDocument){ + xsl=loadXMLDoc(sheetName); + xml=loadXMLDoc(xmlName); + xsltProcessor=new XSLTProcessor(); + xsltProcessor.importStylesheet(xsl); + resultDocument = xsltProcessor.transformToFragment(xml,document); + document.getElementById(htmlDest).appendChild(resultDocument); + } + setClassDisplay("trace","none"); //by default allare visible to protect disabled javascript + } diff --git a/tests/report-styles/jreport.xsl b/tests/report-styles/jreport.xsl new file mode 100644 index 0000000..753a8dc --- /dev/null +++ b/tests/report-styles/jreport.xsl @@ -0,0 +1,215 @@ +<?xml version="1.0"?> +<!-- + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +IcedTea 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 +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. + + --> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> + <xsl:template match="/"> + <h3>Date:</h3> + <xsl:value-of select="/testsuite/date"/> + <br/> + <h2>Result: (<xsl:value-of select="round(sum(/testsuite/testcase/@time) div 1000)"/>s)</h2> + <div class="tablee"> + <div class="row"> + <div class="cell1">TOTAL: </div> + <div class="cell2"> + <xsl:value-of select="/testsuite/stats/summary/total"/> + </div> + <div class="space-line"/> + </div> + <div class="row passed"> + <div class="cell1">passed: </div> + <div class="cell2"> + <xsl:value-of select="/testsuite/stats/summary/passed"/> + </div> + <div class="space-line"/> + </div> + <div class="row failed"> + <div class="cell1">failed: </div> + <div class="cell2"> + <xsl:value-of select="/testsuite/stats/summary/failed"/> + </div> + <div class="space-line"/> + </div> + <div class="row ignored"> + <div class="cell1">ignored: </div> + <div class="cell2"> + <xsl:value-of select="/testsuite/stats/summary/ignored"/> + </div> + <div class="space-line"/> + </div> + </div> + <h2>Classes:</h2> + <xsl:for-each select="/testsuite/stats/classes/class"> + <div> + <xsl:attribute name="class"> + <xsl:choose> + <xsl:when test="passed = total"> + passed + </xsl:when> + <xsl:otherwise> + failed + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <a class="classSumaryName"><xsl:attribute name="href"> + #<xsl:value-of select="@name"/> + </xsl:attribute><xsl:value-of select="@name"/> +(<xsl:value-of select="@time"/>ms): +</a> + </div> + <blockquote> + <div class="tablee"> + <div class="row"> + <div class="cell1">TOTAL: </div> + <div class="cell2"> + <xsl:value-of select="total"/> + </div> + <div class="space-line"/> + </div> + <div class="row passed"> + <div class="cell1">passed: </div> + <div class="cell2"> + <xsl:value-of select="passed"/> + </div> + <div class="space-line"/> + </div> + <div class="row failed"> + <div class="cell1">failed: </div> + <div class="cell2"> + <xsl:value-of select="failed"/> + </div> + <div class="space-line"/> + </div> + <div class="row ignored"> + <div class="cell1">ignored: </div> + <div class="cell2"> + <xsl:value-of select="ignored"/> + </div> + <div class="space-line"/> + </div> + </div> + </blockquote> + <hr/> + </xsl:for-each> + + + <h2>Individual results:</h2> + <button onclick="setClassDisplay('trace','none')">NoneTrace</button> + <button onclick="setClassDisplay('trace','block')">AllTraces</button> + <xsl:for-each select="/testsuite/testcase"> + <div> + <xsl:attribute name="class"> + <xsl:choose> + <xsl:when test="error"> + failed + </xsl:when> + <xsl:otherwise> + passed + </xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <a> + <xsl:attribute name="name"> + <xsl:value-of select="normalize-space(@classname)"/> + </xsl:attribute> + </a> + <div class="lineHeader"> + <div class="clazz"> + <xsl:value-of select="@classname"/> + </div> + <xsl:text disable-output-escaping="no"> - </xsl:text> + <div class="method"> + <xsl:value-of select="@name"/> + </div> + </div> + <div class="result"> + <xsl:choose> + <xsl:when test="not(error)"> + <div class="status"> + PASSED (<xsl:value-of select="@time"/>s) + </div> + </xsl:when> + <xsl:otherwise> + <div class="status"> + FAILED (<xsl:value-of select="@time"/>s) + </div> + <div class="wtrace"> + <div class="theader"> + <xsl:value-of select="error/@type"/> <xsl:text disable-output-escaping="no"> - </xsl:text> + <xsl:value-of select="error/@message"/> + <button onclick="negateIdDisplay('{generate-id(error)}')">StackTrace</button> + </div> + <div class="trace" id="{generate-id(error)}"> + <pre> + <xsl:value-of select="error"/> + </pre> + </div> + </div> + </xsl:otherwise> + </xsl:choose> + <div class="space-line"/> + </div> + <div class="space-line"/> + </div> + <div class="space-line"/> + </xsl:for-each> + + <div class="stbound"> + <div class="theader stExt2"> + STD-OUT - <button onclick="negateIdDisplay('{generate-id(/testsuite/system-out)}')">Show/hide</button> + </div> + <div class="trace stExt3" id="{generate-id(/testsuite/system-out)}"> + <pre> + <xsl:value-of select="/testsuite/system-out"/> + </pre> + </div> + </div> + <div class="space-line"/> + <div class="stbound"> + <div class="theader stExt2"> + STD-ERR - <button onclick="negateIdDisplay('{generate-id(/testsuite/system-err)}')">Show/hide</button> + </div> + <div class="trace stExt3" id="{generate-id(/testsuite/system-err)}"> + <pre> + <xsl:value-of select="/testsuite/system-err"/> + </pre> + </div> + </div> + <div class="space-line"/> + + </xsl:template> +</xsl:stylesheet> diff --git a/tests/report-styles/report.css b/tests/report-styles/report.css new file mode 100644 index 0000000..e0a59c3 --- /dev/null +++ b/tests/report-styles/report.css @@ -0,0 +1,21 @@ +div.passed {background-color:green;height:auto } +div.failed {background-color:red ;height:auto} +div.ignored {background-color:yellow ;height:auto} + +div.clazz {display:inline } +div.method {display:inline } + +div.result {display:block; border: thin solid black ;height:auto} +div.status {display:inline; } +div.wtrace {display:inline; border: thin solid black; float: right;height:auto} +div.theader {display:block; border: thin solid black} +div.trace {display:block; border: thin solid black} + +div.space-line { clear: both; margin: 0; padding: 0; width: auto;} + +div.tablee {width:200px; border: thin solid black; } +div.row { border: thin solid black; } +div.cell1 {display:inline; float: left;height:auto} +div.cell2 {display:inline; float: right;height:auto} + +a.classSumaryName{font-weight:bold} |