• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<?xml version="1.0"?>
2<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
3        xmlns:lxslt="http://xml.apache.org/xslt"
4        xmlns:stringutils="xalan://org.apache.tools.ant.util.StringUtils">
5<xsl:output method="html" indent="yes" encoding="US-ASCII"
6  doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />
7<xsl:decimal-format decimal-separator="." grouping-separator="," />
8<!--
9   Licensed to the Apache Software Foundation (ASF) under one or more
10   contributor license agreements.  See the NOTICE file distributed with
11   this work for additional information regarding copyright ownership.
12   The ASF licenses this file to You under the Apache License, Version 2.0
13   (the "License"); you may not use this file except in compliance with
14   the License.  You may obtain a copy of the License at
15
16       http://www.apache.org/licenses/LICENSE-2.0
17
18   Unless required by applicable law or agreed to in writing, software
19   distributed under the License is distributed on an "AS IS" BASIS,
20   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21   See the License for the specific language governing permissions and
22   limitations under the License.
23 -->
24
25<xsl:param name="TITLE">Unit Test Results.</xsl:param>
26
27<!--
28
29 Sample stylesheet to be used with Ant JUnitReport output.
30
31 It creates a non-framed report that can be useful to send via
32 e-mail or such.
33
34-->
35<xsl:template match="testsuites">
36    <html>
37        <head>
38            <title><xsl:value-of select="$TITLE"/></title>
39    <style type="text/css">
40      body {
41        font:normal 68% verdana,arial,helvetica;
42        color:#000000;
43      }
44      table tr td, table tr th {
45          font-size: 68%;
46      }
47      table.details tr th{
48        font-weight: bold;
49        text-align:left;
50        background:#a6caf0;
51      }
52      table.details tr td{
53        background:#eeeee0;
54      }
55
56      p {
57        line-height:1.5em;
58        margin-top:0.5em; margin-bottom:1.0em;
59      }
60      h1 {
61        margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
62      }
63      h2 {
64        margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
65      }
66      h3 {
67        margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
68      }
69      h4 {
70        margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
71      }
72      h5 {
73        margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
74      }
75      h6 {
76        margin-bottom: 0.5em; font: bold 100% verdana,arial,helvetica
77      }
78      .Error {
79        font-weight:bold; color:red;
80      }
81      .Failure {
82        font-weight:bold; color:purple;
83      }
84      .Properties {
85        text-align:right;
86      }
87      </style>
88      <script type="text/javascript" language="JavaScript">
89        var TestCases = new Array();
90        var cur;
91        <xsl:for-each select="./testsuite">
92            <xsl:apply-templates select="properties"/>
93        </xsl:for-each>
94
95       </script>
96       <script type="text/javascript" language="JavaScript"><![CDATA[
97        function displayProperties (name) {
98          var win = window.open('','JUnitSystemProperties','scrollbars=1,resizable=1');
99          var doc = win.document;
100          doc.open();
101          doc.write("<html><head><title>Properties of " + name + "</title>");
102          doc.write("<style>")
103          doc.write("body {font:normal 68% verdana,arial,helvetica; color:#000000; }");
104          doc.write("table tr td, table tr th { font-size: 68%; }");
105          doc.write("table.properties { border-collapse:collapse; border-left:solid 1 #cccccc; border-top:solid 1 #cccccc; padding:5px; }");
106          doc.write("table.properties th { text-align:left; border-right:solid 1 #cccccc; border-bottom:solid 1 #cccccc; background-color:#eeeeee; }");
107          doc.write("table.properties td { font:normal; text-align:left; border-right:solid 1 #cccccc; border-bottom:solid 1 #cccccc; background-color:#fffffff; }");
108          doc.write("h3 { margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica }");
109          doc.write("</style>");
110          doc.write("</head><body>");
111          doc.write("<h3>Properties of " + name + "</h3>");
112          doc.write("<div align=\"right\"><a href=\"javascript:window.close();\">Close</a></div>");
113          doc.write("<table class='properties'>");
114          doc.write("<tr><th>Name</th><th>Value</th></tr>");
115          for (prop in TestCases[name]) {
116            doc.write("<tr><th>" + prop + "</th><td>" + TestCases[name][prop] + "</td></tr>");
117          }
118          doc.write("</table>");
119          doc.write("</body></html>");
120          doc.close();
121          win.focus();
122        }
123      ]]>
124      </script>
125        </head>
126        <body>
127            <a name="top"></a>
128            <xsl:call-template name="pageHeader"/>
129
130            <!-- Summary part -->
131            <xsl:call-template name="summary"/>
132            <hr size="1" width="95%" align="left"/>
133
134            <!-- Package List part -->
135            <xsl:call-template name="packagelist"/>
136            <hr size="1" width="95%" align="left"/>
137
138            <!-- For each package create its part -->
139            <xsl:call-template name="packages"/>
140            <hr size="1" width="95%" align="left"/>
141
142            <!-- For each class create the  part -->
143            <xsl:call-template name="classes"/>
144
145        </body>
146    </html>
147</xsl:template>
148
149
150
151    <!-- ================================================================== -->
152    <!-- Write a list of all packages with an hyperlink to the anchor of    -->
153    <!-- of the package name.                                               -->
154    <!-- ================================================================== -->
155    <xsl:template name="packagelist">
156        <h2>Packages</h2>
157        Note: package statistics are not computed recursively, they only sum up all of its testsuites numbers.
158        <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
159            <xsl:call-template name="testsuite.test.header"/>
160            <!-- list all packages recursively -->
161            <xsl:for-each select="./testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
162                <xsl:sort select="@package"/>
163                <xsl:variable name="testsuites-in-package" select="/testsuites/testsuite[./@package = current()/@package]"/>
164                <xsl:variable name="testCount" select="sum($testsuites-in-package/@tests)"/>
165                <xsl:variable name="errorCount" select="sum($testsuites-in-package/@errors)"/>
166                <xsl:variable name="failureCount" select="sum($testsuites-in-package/@failures)"/>
167                <xsl:variable name="timeCount" select="sum($testsuites-in-package/@time)"/>
168
169                <!-- write a summary for the package -->
170                <tr valign="top">
171                    <!-- set a nice color depending if there is an error/failure -->
172                    <xsl:attribute name="class">
173                        <xsl:choose>
174                            <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
175                            <xsl:when test="$errorCount &gt; 0">Error</xsl:when>
176                        </xsl:choose>
177                    </xsl:attribute>
178                    <td><a href="#{@package}"><xsl:value-of select="@package"/></a></td>
179                    <td><xsl:value-of select="$testCount"/></td>
180                    <td><xsl:value-of select="$errorCount"/></td>
181                    <td><xsl:value-of select="$failureCount"/></td>
182                    <td>
183                    <xsl:call-template name="display-time">
184                        <xsl:with-param name="value" select="$timeCount"/>
185                    </xsl:call-template>
186                    </td>
187                    <td><xsl:value-of select="$testsuites-in-package/@timestamp"/></td>
188                    <td><xsl:value-of select="$testsuites-in-package/@hostname"/></td>
189                </tr>
190            </xsl:for-each>
191        </table>
192    </xsl:template>
193
194
195    <!-- ================================================================== -->
196    <!-- Write a package level report                                       -->
197    <!-- It creates a table with values from the document:                  -->
198    <!-- Name | Tests | Errors | Failures | Time                            -->
199    <!-- ================================================================== -->
200    <xsl:template name="packages">
201        <!-- create an anchor to this package name -->
202        <xsl:for-each select="/testsuites/testsuite[not(./@package = preceding-sibling::testsuite/@package)]">
203            <xsl:sort select="@package"/>
204                <a name="{@package}"></a>
205                <h3>Package <xsl:value-of select="@package"/></h3>
206
207                <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
208                    <xsl:call-template name="testsuite.test.header"/>
209
210                    <!-- match the testsuites of this package -->
211                    <xsl:apply-templates select="/testsuites/testsuite[./@package = current()/@package]" mode="print.test"/>
212                </table>
213                <a href="#top">Back to top</a>
214                <p/>
215                <p/>
216        </xsl:for-each>
217    </xsl:template>
218
219    <xsl:template name="classes">
220        <xsl:for-each select="testsuite">
221            <xsl:sort select="@name"/>
222            <!-- create an anchor to this class name -->
223            <a name="{@name}"></a>
224            <h3>TestCase <xsl:value-of select="@name"/></h3>
225
226            <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
227              <xsl:call-template name="testcase.test.header"/>
228              <!--
229              test can even not be started at all (failure to load the class)
230              so report the error directly
231              -->
232                <xsl:if test="./error">
233                    <tr class="Error">
234                        <td colspan="4"><xsl:apply-templates select="./error"/></td>
235                    </tr>
236                </xsl:if>
237                <xsl:apply-templates select="./testcase" mode="print.test"/>
238            </table>
239            <div class="Properties">
240                <a>
241                    <xsl:attribute name="href">javascript:displayProperties('<xsl:value-of select="@package"/>.<xsl:value-of select="@name"/>');</xsl:attribute>
242                    Properties &#187;
243                </a>
244            </div>
245            <p/>
246
247            <a href="#top">Back to top</a>
248        </xsl:for-each>
249    </xsl:template>
250
251    <xsl:template name="summary">
252        <h2>Summary</h2>
253        <xsl:variable name="testCount" select="sum(testsuite/@tests)"/>
254        <xsl:variable name="errorCount" select="sum(testsuite/@errors)"/>
255        <xsl:variable name="failureCount" select="sum(testsuite/@failures)"/>
256        <xsl:variable name="timeCount" select="sum(testsuite/@time)"/>
257        <xsl:variable name="successRate" select="($testCount - $failureCount - $errorCount) div $testCount"/>
258        <table class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
259        <tr valign="top">
260            <th>Tests</th>
261            <th>Failures</th>
262            <th>Errors</th>
263            <th>Success rate</th>
264            <th>Time</th>
265        </tr>
266        <tr valign="top">
267            <xsl:attribute name="class">
268                <xsl:choose>
269                    <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
270                    <xsl:when test="$errorCount &gt; 0">Error</xsl:when>
271                </xsl:choose>
272            </xsl:attribute>
273            <td><xsl:value-of select="$testCount"/></td>
274            <td><xsl:value-of select="$failureCount"/></td>
275            <td><xsl:value-of select="$errorCount"/></td>
276            <td>
277                <xsl:call-template name="display-percent">
278                    <xsl:with-param name="value" select="$successRate"/>
279                </xsl:call-template>
280            </td>
281            <td>
282                <xsl:call-template name="display-time">
283                    <xsl:with-param name="value" select="$timeCount"/>
284                </xsl:call-template>
285            </td>
286
287        </tr>
288        </table>
289        <table border="0" width="95%">
290        <tr>
291        <td style="text-align: justify;">
292        Note: <i>failures</i> are anticipated and checked for with assertions while <i>errors</i> are unanticipated.
293        </td>
294        </tr>
295        </table>
296    </xsl:template>
297
298  <!--
299   Write properties into a JavaScript data structure.
300   This is based on the original idea by Erik Hatcher (ehatcher@apache.org)
301   -->
302  <xsl:template match="properties">
303    cur = TestCases['<xsl:value-of select="../@package"/>.<xsl:value-of select="../@name"/>'] = new Array();
304    <xsl:for-each select="property">
305    <xsl:sort select="@name"/>
306        cur['<xsl:value-of select="@name"/>'] = '<xsl:call-template name="JS-escape"><xsl:with-param name="string" select="@value"/></xsl:call-template>';
307    </xsl:for-each>
308  </xsl:template>
309
310<!-- Page HEADER -->
311<xsl:template name="pageHeader">
312    <h1><xsl:value-of select="$TITLE"/></h1>
313    <table width="100%">
314    <tr>
315        <td align="left"></td>
316        <td align="right">Designed for use with <a href='http://www.junit.org'>JUnit</a> and <a href='http://ant.apache.org/ant'>Ant</a>.</td>
317    </tr>
318    </table>
319    <hr size="1"/>
320</xsl:template>
321
322<xsl:template match="testsuite" mode="header">
323    <tr valign="top">
324        <th width="80%">Name</th>
325        <th>Tests</th>
326        <th>Errors</th>
327        <th>Failures</th>
328        <th nowrap="nowrap">Time(s)</th>
329    </tr>
330</xsl:template>
331
332<!-- class header -->
333<xsl:template name="testsuite.test.header">
334    <tr valign="top">
335        <th width="80%">Name</th>
336        <th>Tests</th>
337        <th>Errors</th>
338        <th>Failures</th>
339        <th nowrap="nowrap">Time(s)</th>
340        <th nowrap="nowrap">Time Stamp</th>
341        <th>Host</th>
342    </tr>
343</xsl:template>
344
345<!-- method header -->
346<xsl:template name="testcase.test.header">
347    <tr valign="top">
348        <th>Name</th>
349        <th>Status</th>
350        <th width="80%">Type</th>
351        <th nowrap="nowrap">Time(s)</th>
352    </tr>
353</xsl:template>
354
355
356<!-- class information -->
357<xsl:template match="testsuite" mode="print.test">
358    <tr valign="top">
359        <!-- set a nice color depending if there is an error/failure -->
360        <xsl:attribute name="class">
361            <xsl:choose>
362                <xsl:when test="@failures[.&gt; 0]">Failure</xsl:when>
363                <xsl:when test="@errors[.&gt; 0]">Error</xsl:when>
364            </xsl:choose>
365        </xsl:attribute>
366
367        <!-- print testsuite information -->
368        <td><a href="#{@name}"><xsl:value-of select="@name"/></a></td>
369        <td><xsl:value-of select="@tests"/></td>
370        <td><xsl:value-of select="@errors"/></td>
371        <td><xsl:value-of select="@failures"/></td>
372        <td>
373            <xsl:call-template name="display-time">
374                <xsl:with-param name="value" select="@time"/>
375            </xsl:call-template>
376        </td>
377        <td><xsl:apply-templates select="@timestamp"/></td>
378        <td><xsl:apply-templates select="@hostname"/></td>
379    </tr>
380</xsl:template>
381
382<xsl:template match="testcase" mode="print.test">
383    <tr valign="top">
384        <xsl:attribute name="class">
385            <xsl:choose>
386                <xsl:when test="failure | error">Error</xsl:when>
387            </xsl:choose>
388        </xsl:attribute>
389        <td><xsl:value-of select="@name"/></td>
390        <xsl:choose>
391            <xsl:when test="failure">
392                <td>Failure</td>
393                <td><xsl:apply-templates select="failure"/></td>
394            </xsl:when>
395            <xsl:when test="error">
396                <td>Error</td>
397                <td><xsl:apply-templates select="error"/></td>
398            </xsl:when>
399            <xsl:otherwise>
400                <td>Success</td>
401                <td></td>
402            </xsl:otherwise>
403        </xsl:choose>
404        <td>
405            <xsl:call-template name="display-time">
406                <xsl:with-param name="value" select="@time"/>
407            </xsl:call-template>
408        </td>
409    </tr>
410</xsl:template>
411
412
413<xsl:template match="failure">
414    <xsl:call-template name="display-failures"/>
415</xsl:template>
416
417<xsl:template match="error">
418    <xsl:call-template name="display-failures"/>
419</xsl:template>
420
421<!-- Style for the error and failure in the tescase template -->
422<xsl:template name="display-failures">
423    <xsl:choose>
424        <xsl:when test="not(@message)">N/A</xsl:when>
425        <xsl:otherwise>
426            <xsl:value-of select="@message"/>
427        </xsl:otherwise>
428    </xsl:choose>
429    <!-- display the stacktrace -->
430    <code>
431        <br/><br/>
432        <xsl:call-template name="br-replace">
433            <xsl:with-param name="word" select="."/>
434        </xsl:call-template>
435    </code>
436    <!-- the later is better but might be problematic for non-21" monitors... -->
437    <!--pre><xsl:value-of select="."/></pre-->
438</xsl:template>
439
440<xsl:template name="JS-escape">
441    <xsl:param name="string"/>
442    <xsl:param name="tmp1" select="stringutils:replace(string($string),'\','\\')"/>
443    <xsl:param name="tmp2" select="stringutils:replace(string($tmp1),&quot;'&quot;,&quot;\&apos;&quot;)"/>
444    <xsl:value-of select="$tmp2"/>
445</xsl:template>
446
447
448<!--
449    template that will convert a carriage return into a br tag
450    @param word the text from which to convert CR to BR tag
451-->
452<xsl:template name="br-replace">
453    <xsl:param name="word"/>
454    <xsl:value-of disable-output-escaping="yes" select='stringutils:replace(string($word),"&#xA;","&lt;br/>")'/>
455</xsl:template>
456
457<xsl:template name="display-time">
458    <xsl:param name="value"/>
459    <xsl:value-of select="format-number($value,'0.000')"/>
460</xsl:template>
461
462<xsl:template name="display-percent">
463    <xsl:param name="value"/>
464    <xsl:value-of select="format-number($value,'0.00%')"/>
465</xsl:template>
466
467</xsl:stylesheet>
468