All, I have created a Summary Report XSL for the NUnit2 test results XML. I based this off of Tomas Restrepo's version in the Winterdom add on to NAnt. You can simply set the xslfile attribute on your NUnitReport task to use this transformation. There are two files, NUnit2Summary.xsl and toolkit2.xsl that you will need to run the transform.
Enjoy! -Aaron <!--------------------------(NUnit2Summary.xsl)--------------------------------> <?xml version="1.0" encoding="ISO-8859-1"?> <!-- This XSL File is based on the summary_overview.xsl template created by Erik Hatcher fot Ant's JUnitReport. Original XSL Modified by Tomas Restrepo ([EMAIL PROTECTED]) for use with NUnitReport Task and NUnit v1 Modified by Aaron Sansone ([EMAIL PROTECTED]) for use with NUnit2 --> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:html="http://www.w3.org/Profiles/XHTML-transitional"> <xsl:output method="html" indent="yes"/> <xsl:include href="toolkit2.xsl"/> <!-- ==================================================== Create the page structure ==================================================== --> <xsl:template match="testsummary"> <HTML> <HEAD> <!--LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style"/--> <!-- put the style in the html so that we can mail it w/o problem --> <style type="text/css"> BODY { font:normal 68% verdana,arial,helvetica; color:#000000; } TD { FONT-SIZE: 68% } 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; background:#EEEEE0; color:purple; } .Failure { font-weight:bold; background:#EEEEE0; color:red; } .NotRun { font-weight:bold; background:#EEEEE0; color:orange; } .FailureDetail { font-size: -1; padding-left: 2.0em; } .Pass { background:#EEEEE0; } .TableHeader { background: #6699cc; color: white; font-weight: bold; horizontal-align: center; } .EnvInfoHeader { background: #ff0000; color: white; font-weight: bold; horizontal-align: center; } .EnvInfoRow { background:#EEEEE0 } A:visited { color: #0000ff; } A { color: #0000ff; } A:active { color: #800000; } </style> <script language="JavaScript"><![CDATA[ function toggle (field) { field.style.display = (field.style.display == "block") ? "none" : "block"; } ]]> </script> </HEAD> <body text="#000000" bgColor="#ffffff"> <a name="#top"></a> <xsl:call-template name="header"/> <!-- Summary part --> <xsl:call-template name="summary"/> <hr size="1" width="95%" align="left"/> <!-- Package List part --> <xsl:call-template name="testResultsList"/> <hr size="1" width="95%" align="left"/> <!-- Environment info part --> <xsl:call-template name="envinfo"/> </body> </HTML> </xsl:template> <xsl:template name="testResultsList"> <xsl:for-each select="descendant::test-results"> <a name="#{generate-id(@name)}"></a><h2>TestSuite Summary</h2> <h2><xsl:value-of select="@name"/></h2> <xsl:call-template name="suiteSummary"/> <xsl:call-template name="testSuiteList"/> <hr/> </xsl:for-each> <h2>TestCase Summary</h2> <xsl:for-each select="descendant::test-suite[child::results/child::test-case[position()=1]]"> <a name="#{generate-id(@name)}"></a><h2><xsl:value-of select="@name"/></h2> <xsl:call-template name="testCases"/> <a href="#top">Back to top</a> <hr/> </xsl:for-each> </xsl:template> <!-- ================================================================== --> <!-- Write a list of all packages with an hyperlink to the anchor of --> <!-- of the package name. --> <!-- ================================================================== --> <xsl:template name="testSuiteList"> <table border="0" cellpadding="5" cellspacing="2" width="95%"> <xsl:call-template name="testSuiteSummaryHeader"/> <!-- list all packages recursively --> <xsl:for-each select="descendant::test-suite[child::results/child::test-case[position()=1]]"> <xsl:sort select="@name"/> <xsl:variable name="hasIgnoredTests"> <xsl:choose> <xsl:when test="child::results/child::test-case/reason">True</xsl:when> <xsl:otherwise>False</xsl:otherwise> </xsl:choose> </xsl:variable> <!-- write a summary for the package --> <tr valign="top"> <!-- set a nice color depending if there is an error/failure --> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="@success = "False"">Failure</xsl:when> <xsl:when test="$hasIgnoredTests = "True"">NotRun</xsl:when> <xsl:otherwise>Pass</xsl:otherwise> </xsl:choose> </xsl:attribute> <td><a href="#{generate-id(@name)}"><xsl:value-of select="@name"/></a></td> <td><xsl:value-of select="@success"/></td> <td> <xsl:call-template name="display-time"> <xsl:with-param name="value" select="@time"/> </xsl:call-template> </td> </tr> </xsl:for-each> </table> </xsl:template> <xsl:template name="testCases"> <table border="0" cellpadding="5" cellspacing="2" width="95%"> <xsl:call-template name="testCaseSummaryHeader"/> <xsl:for-each select="descendant::test-case"> <xsl:variable name="result"> <xsl:choose> <xsl:when test="./failure">Failure</xsl:when> <xsl:when test="./error">Error</xsl:when> <xsl:when test="./reason">NotRun</xsl:when> <xsl:otherwise>Pass</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="newid" select="generate-id(@name)" /> <!-- write a summary for the test case --> <tr valign="top"> <!-- set a nice color depending if there is an error/failure/NotRun --> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="@success = "False"">Failure</xsl:when> <xsl:when test="@executed = "False"">NotRun</xsl:when> <xsl:otherwise>Pass</xsl:otherwise> </xsl:choose> </xsl:attribute> <td><xsl:value-of select="@name"/></td> <td><xsl:value-of select="@executed"/></td> <td><xsl:value-of select="@success"/></td> <td> <xsl:call-template name="display-time"> <xsl:with-param name="value" select="@time"/> </xsl:call-template> </td> </tr> <xsl:if test="$result != "Pass""> <tr style="display: block;"> <xsl:attribute name="id"> <xsl:value-of select="$newid"/> </xsl:attribute> <td colspan="3" class="FailureDetail"> <xsl:apply-templates select="./failure"/> <xsl:apply-templates select="./error"/> <xsl:apply-templates select="./reason"/> </td> </tr> </xsl:if> </xsl:for-each> </table> </xsl:template> <xsl:template name="dot-replace"> <xsl:param name="package"/> <xsl:choose> <xsl:when test="contains($package,'.')"><xsl:value-of select="substring-before($package,'.')"/>_<xsl:call-template name="dot-replace"><xsl:with-param name="package" select="substring-after($package,'.')"/></xsl:call-template></xsl:when> <xsl:otherwise><xsl:value-of select="$package"/></xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet> <!--------------------------(toolkit2.xsl)--------------------------------> <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:param name="nant.filename" /> <xsl:param name="nant.version" /> <xsl:param name="nant.project.name" /> <xsl:param name="nant.project.buildfile" /> <xsl:param name="nant.project.basedir" /> <xsl:param name="nant.project.default" /> <xsl:param name="sys.os" /> <xsl:param name="sys.os.platform" /> <xsl:param name="sys.os.version" /> <xsl:param name="sys.clr.version" /> <!-- This XSL File is based on the toolkit.xsl template created by Erik Hatcher fot Ant's JUnitReport Original XSL Modified by Tomas Restrepo ([EMAIL PROTECTED]) for use with NUnitReport Task and NUnit v1 Modified by Aaron Sansone ([EMAIL PROTECTED]) for use with NUnit2 --> <!-- format a number in to display its value in percent @param value the number to format --> <xsl:template name="display-time"> <xsl:param name="value"/> <xsl:value-of select="format-number($value,'0.000')"/> </xsl:template> <!-- format a number in to display its value in percent @param value the number to format --> <xsl:template name="display-percent"> <xsl:param name="value"/> <xsl:value-of select="format-number($value,'0.00%')"/> </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> <!-- 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:choose> <xsl:when test="contains($word,'
')"> <xsl:value-of select="substring-before($word,'
')"/> <br/> <xsl:call-template name="br-replace"> <xsl:with-param name="word" select="substring-after($word,'
')"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:value-of select="$word"/> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- ===================================================================== classes summary header ===================================================================== --> <xsl:template name="header"> <xsl:param name="path"/> <h1>Unit Tests Results - <xsl:value-of select="$nant.project.name"/></h1> <table width="100%"> <tr> <td align="left"> Generated: <xsl:value-of select="@created"/> - <a href="#envinfo">Environment Information</a> </td> <td align="right">Designed for use with <a href='http://nunit.sourceforge.net/'>NUnit</a> and <a href='http://nant.sourceforge.net/'>NAnt</a>. </td> </tr> </table> <hr size="1"/> </xsl:template> <xsl:template name="summaryHeader"> <tr valign="top" class="TableHeader"> <td><b>Total Tests</b></td> <td><b>Total Failures</b></td> <td><b>Total Tests Not Run</b></td> <td><b>Success Rate</b></td> <td nowrap="nowrap"><b>Time(s)</b></td> </tr> </xsl:template> <!-- ===================================================================== test Suite summary header ===================================================================== --> <xsl:template name="testSuiteSummaryHeader"> <tr class="TableHeader" valign="top"> <td width="85%"><b>Name</b></td> <td width="5%"><b>Success</b></td> <td width="10%" nowrap="nowrap"><b>Time(s)</b></td> </tr> </xsl:template> <!-- ===================================================================== test Case summary header ===================================================================== --> <xsl:template name="testCaseSummaryHeader"> <tr class="TableHeader" valign="top"> <td width="80%"><b>Name</b></td> <td width="5%"><b>Executed</b></td> <td width="5%"><b>Success</b></td> <td width="10%" nowrap="nowrap"><b>Time(s)</b></td> </tr> </xsl:template> <!-- ===================================================================== Write the summary report It creates a table with computed values from the document: User | Date | Environment | Tests | Failures | Errors | Rate | Time Note : this template must call at the testsuites level ===================================================================== --> <xsl:template name="summary"> <h2>Summary</h2> Assemblies: <br/> <xsl:for-each select="descendant::test-results"> <a href="#{generate-id(@name)}"><xsl:value-of select="@name"/></a><br/> </xsl:for-each> <br/> <xsl:variable name="testCount" select="sum(descendant::test-results/@total)"/> <xsl:variable name="notRunCount" select="sum(descendant::test-results/@not-run)"/> <xsl:variable name="failureCount" select="sum(descendant::test-results/@failures)"/> <xsl:variable name="timeCount" select="sum(descendant::test-results/test-suite/@time)"/> <xsl:variable name="successRate" select="($testCount - $failureCount - $notRunCount) div $testCount"/> <table border="0" cellpadding="5" cellspacing="2" width="95%"> <xsl:call-template name="summaryHeader"/> <tr valign="top"> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="$failureCount > 0">Failure</xsl:when> <xsl:when test="$notRunCount > 0">NotRun</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="$notRunCount"/></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> </xsl:template> <!-- ===================================================================== Write the suite summary report ===================================================================== --> <xsl:template name="suiteSummary"> <table border="0" cellpadding="5" cellspacing="2" width="95%"> <xsl:call-template name="summaryHeader"/> <xsl:variable name="timeCount" select="sum(descendant::test-suite[child::results/child::test-case[position()=1] ]/@time)"/> <xsl:variable name="successRate" select="(@total - @failures - @not-run) div @total"/> <tr valign="top"> <xsl:attribute name="class"> <xsl:choose> <xsl:when test="@failures > 0">Failure</xsl:when> <xsl:when test="@not-run > 0">NotRun</xsl:when> <xsl:otherwise>Pass</xsl:otherwise> </xsl:choose> </xsl:attribute> <td><xsl:value-of select="@total"/></td> <td><xsl:value-of select="@failures"/></td> <td><xsl:value-of select="@not-run"/></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> </xsl:template> <!-- ===================================================================== testcase report ===================================================================== --> <xsl:template match="test-case"> <xsl:variable name="result"> <xsl:choose> <xsl:when test="./failure">Failure</xsl:when> <xsl:when test="./error">Error</xsl:when> <xsl:otherwise>Pass</xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:variable name="newid" select="generate-id(@name)" /> <TR valign="top"> <xsl:attribute name="class"><xsl:value-of select="$result"/></xsl:attribute> <xsl:if test="$result != "Pass""> <xsl:attribute name="onclick">javascript:ToggleRow(<xsl:value-of select="$newid"/>)</xsl:attribute> <xsl:attribute name="style">cursor: hand;</xsl:attribute> </xsl:if> <TD><xsl:value-of select="./@name"/></TD> <td><xsl:value-of select="$result"/></td> <td> <xsl:call-template name="display-time"> <xsl:with-param name="value" select="@time"/> </xsl:call-template> </td> </TR> <xsl:if test="$result != "Pass""> <tr style="display: block;"> <xsl:attribute name="id"> <xsl:value-of select="$newid"/> </xsl:attribute> <td colspan="3" class="FailureDetail"> <xsl:apply-templates select="./failure"/> <xsl:apply-templates select="./error"/> </td> </tr> </xsl:if> </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> <xsl:template match="notrun"> <xsl:call-template name="display-failures"/> </xsl:template> <!-- Style for the error and failure in the tescase template --> <xsl:template name="display-failures"> <pre> <xsl:value-of select="./message"/> </pre> <!-- display the stacktrace --> <code> <p/> <xsl:call-template name="br-replace"> <xsl:with-param name="word" select="./stack-trace"/> </xsl:call-template> </code> <!-- the later is better but might be problematic for non-21" monitors... --> <!--pre><xsl:value-of select="."/></pre--> </xsl:template> <!-- ===================================================================== Environtment Info Report ===================================================================== --> <xsl:template name="envinfo"> <a name="envinfo"></a> <h2>Environment Information</h2> <table border="0" cellpadding="5" cellspacing="2" width="95%"> <tr class="EnvInfoHeader"> <td>Property</td> <td>Value</td> </tr> <tr class="EnvInfoRow"> <td>NAnt Location</td> <td><xsl:value-of select="$nant.filename"/></td> </tr> <tr class="EnvInfoRow"> <td>NAnt Version</td> <td><xsl:value-of select="$nant.version"/></td> </tr> <tr class="EnvInfoRow"> <td>Buildfile</td> <td><xsl:value-of select="$nant.project.buildfile"/></td> </tr> <tr class="EnvInfoRow"> <td>Base Directory</td> <td><xsl:value-of select="$nant.project.basedir"/></td> </tr> <tr class="EnvInfoRow"> <td>Operating System</td> <td><xsl:value-of select="$sys.os"/></td> <!-- If this doesn't look right, your version of NAnt has a broken sysinfo task... <td><xsl:value-of select="$sys.os.platform"/> - <xsl:value-of select="$sys.os.version"/></td> or <td><xsl:value-of select="$sys.os.version"/></td> --> </tr> <tr class="EnvInfoRow"> <td>.NET CLR Version</td> <td><xsl:value-of select="$sys.clr.version"/></td> </tr> </table> <a href="#top">Back to top</a> </xsl:template> <!-- I am sure that all nodes are called --> <xsl:template match="*"> <xsl:apply-templates/> </xsl:template> </xsl:stylesheet> ------------------------------------------------------- This SF.NET email is sponsored by: SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See! http://www.vasoftware.com _______________________________________________ Nant-developers mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/nant-developers
