From: <bo...@us...> - 2010-06-21 14:37:58
|
Revision: 404 http://xmlunit.svn.sourceforge.net/xmlunit/?rev=404&view=rev Author: bodewig Date: 2010-06-21 14:37:51 +0000 (Mon, 21 Jun 2010) Log Message: ----------- node type independent comparisons Modified Paths: -------------- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DifferenceEvaluators.java trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs trunk/xmlunit/xmlunit.nant.build Added Paths: ----------- trunk/xmlunit/lib/NUnitSummary.xsl trunk/xmlunit/lib/toolkit.xsl Added: trunk/xmlunit/lib/NUnitSummary.xsl =================================================================== --- trunk/xmlunit/lib/NUnitSummary.xsl (rev 0) +++ trunk/xmlunit/lib/NUnitSummary.xsl 2010-06-21 14:37:51 UTC (rev 404) @@ -0,0 +1,214 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- +The goal of the NUnit2Report task is to merge the individual XML files generated by the NUnit2 task and apply a stylesheet on the resulting merged document to provide a browsable report of the testcases results. + +This project is host on Sourceforge http://sourceforge.net/projects/nunit2report/ + +NUnit2Report 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 of the License, or (at your option) any later version. +--> +<!-- + This XSL File is based on the NUnitSummary.xsl + template created by Tomas Restrepo fot NAnt's NUnitReport. + + Modified by Gilles Bayon (gil...@la...) for use + with NUnit2Report. + +--> +<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="toolkit.xsl"/> + <xsl:preserve-space elements="a root"/> + + +<!-- + ==================================================== + Create the page structure + ==================================================== +--> +<xsl:template match="test-results"> + <HTML> + <HEAD> + <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; + } + .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"/> + <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="packagelist"/> + <hr size="1" width="95%" align="left"/> + + <!-- For each testsuite create the part --> + <xsl:call-template name="testsuites"/> + <hr size="1" width="95%" align="left"/> + + <!-- Environment info part --> + + <xsl:call-template name="envinfo"/> + + </body> + </HTML> +</xsl:template> + + + + <!-- ================================================================== --> + <!-- Write a list of all packages with an hyperlink to the anchor of --> + <!-- of the package name. --> + <!-- ================================================================== --> + <xsl:template name="packagelist"> + <h2 id=":i18n:TestSuiteSummary">TestSuite Summary</h2> + <table border="0" cellpadding="5" cellspacing="2" width="95%"> + <xsl:call-template name="packageSummaryHeader"/> + <!-- list all packages recursively --> + <xsl:for-each select="//test-suite[(child::results/test-case)]"> + <xsl:sort select="@name"/> + <xsl:variable name="testCount" select="count(child::results/test-case)"/> + <xsl:variable name="errorCount" select="count(child::results/test-case[@executed='False'])"/> + <xsl:variable name="failureCount" select="count(child::results/test-case[@success='False'])"/> + <xsl:variable name="timeCount" select="concat(substring-before(@time,','),'.',substring-after(@time,','))"/> + + <!-- 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="$failureCount > 0">Failure</xsl:when> + <xsl:when test="$errorCount > 0"> Error</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="$testCount"/> + </td> + <td><xsl:value-of select="$errorCount"/></td> + <td><xsl:value-of select="$failureCount"/></td> + <td> + <xsl:call-template name="display-time"> + <xsl:with-param name="value" select="$timeCount"/> + </xsl:call-template> + </td> + </tr> + </xsl:for-each> + </table> + </xsl:template> + + + <xsl:template name="testsuites"> + <script language="JScript"><![CDATA[ + function ToggleRow(id) { + if ( id.style.display == "none" ) + id.style.display = "block"; + else + id.style.display = "none"; + } + ]]></script> + + <xsl:for-each select="//test-suite[(child::results/test-case)]"> + <xsl:sort select="@name"/> + <!-- create an anchor to this class name --> + <a name="#{generate-id(@name)}"/> + <h3>TestSuite <xsl:value-of select="@name"/></h3> + + <table border="0" cellpadding="5" cellspacing="2" width="95%"> + <!-- Header --> + <xsl:call-template name="classesSummaryHeader"/> + + <!-- match the testcases of this package --> + <xsl:apply-templates select="results/test-case"> + <xsl:sort select="@name"/> + </xsl:apply-templates> + </table> + <a href="#top" id=":i18n:Backtotop">Back to top</a> + </xsl:for-each> + </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> \ No newline at end of file Property changes on: trunk/xmlunit/lib/NUnitSummary.xsl ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/xmlunit/lib/toolkit.xsl =================================================================== --- trunk/xmlunit/lib/toolkit.xsl (rev 0) +++ trunk/xmlunit/lib/toolkit.xsl 2010-06-21 14:37:51 UTC (rev 404) @@ -0,0 +1,420 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<!-- +The goal of the NUnit2Report task is to merge the individual XML files generated by the NUnit2 task and apply a stylesheet on the resulting merged document to provide a browsable report of the testcases results. + +This project is host on Sourceforge http://sourceforge.net/projects/nunit2report/ + +NUnit2Report 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 of the License, or (at your option) any later version. +--> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:nunit2report="urn:my-scripts"> +<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"/> + +<msxsl:script language="C#" implements-prefix="nunit2report"> + + public string TestCaseName(string path) { + + string[] a = path.Split('.'); + + return(a[a.Length-1]); + } + +</msxsl:script> + +<!-- + TO DO + Corriger les alignement sur error + Couleur http://nanning.sourceforge.net/junit-report.html +--> + + +<!-- + 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><span id=":i18n:UnitTestsResults">Unit Tests Results</span> - <xsl:value-of select="$nant.project.name"/></h1> + <table width="100%"> + <tr> + <td align="left"> + <span id=":i18n:GeneratedBy">Generated by</span>\xA0<a target="_blank" href="http://sourceforge.net/projects/nunit2report/">NUnit2Report</a> : <xsl:value-of select="@date"/> - <xsl:value-of select="concat(@time,' ')"/>\xA0<a href="#envinfo" id=":i18n:EnvironmentInformation">Environment Information</a> + </td> + <td align="right"><span id=":i18n:Designed">Designed for use with</span>\xA0<a href="http://nunit.sourceforge.net/">NUnit</a>\xA0<span id=":i18n:and">and</span>\xA0<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 width="50px"><b id=":i18n:Tests">Tests</b></td> + <td width="70px"><b id=":i18n:Failures">Failures</b></td> + <td width="70px"><b id=":i18n:Errors">Errors</b></td> + <td colspan="2"><b id=":i18n:SuccessRate">Success Rate</b></td> + <td width="70px" nowrap="nowrap"><b id=":i18n:Time">Time(s)</b></td> + </tr> +</xsl:template> + +<!-- + ===================================================================== + package summary header + ===================================================================== +--> +<xsl:template name="packageSummaryHeader"> + <tr class="TableHeader" valign="top"> + <td width="75%" colspan="3"><b id=":i18n:Name">Name</b></td> + <td width="5%"><b id=":i18n:Tests">Tests</b></td> + <td width="5%"><b id=":i18n:Errors">Errors</b></td> + <td width="5%"><b id=":i18n:Failures">Failures</b></td> + <td width="10%" nowrap="nowrap"><b id=":i18n:Time">Time(s)</b></td> + </tr> +</xsl:template> + + +<!-- + ===================================================================== + classes summary header + ===================================================================== +--> +<xsl:template name="classesSummaryHeader"> + <tr class="TableHeader" valign="top"> + <td width="85%" colspan="2"><b id=":i18n:Name">Name</b></td> + <td width="10%"><b id=":i18n:Status">Status</b></td> + <td width="5%" nowrap="nowrap"><b id=":i18n:Time">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 id=":i18n:Summary">Summary</h2> + <xsl:variable name="runCount" select="@total"/> + <xsl:variable name="failureCount" select="@failures"/> + <xsl:variable name="ignoreCount" select="@not-run"/> + <xsl:variable name="total" select="$runCount + $ignoreCount + $failureCount"/> + + <xsl:variable name="timeCount" select="translate(test-suite/@time,',','.')"/> + + <xsl:variable name="successRate" select="$runCount div $total"/> + <table border="0" cellpadding="2" cellspacing="0" width="95%" style="border: #dcdcdc 1px solid;"> + <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="$ignoreCount > 0">Error</xsl:when> + <xsl:otherwise>Pass</xsl:otherwise> + </xsl:choose> + </xsl:attribute> + <td><xsl:value-of select="$runCount"/></td> + <td><xsl:value-of select="$failureCount"/></td> + <td><xsl:value-of select="$ignoreCount"/></td> + <td nowrap="nowrap" width="70px"> + <xsl:call-template name="display-percent"> + <xsl:with-param name="value" select="$successRate"/> + </xsl:call-template> + </td> + <td> + <xsl:if test="round($runCount * 200 div $total )!=0"> + <span class="covered"> + <xsl:attribute name="style">width:<xsl:value-of select="round($runCount * 200 div $total )"/>px</xsl:attribute> + </span> + </xsl:if> + <xsl:if test="round($ignoreCount * 200 div $total )!=0"> + <span class="ignored"> + <xsl:attribute name="style">width:<xsl:value-of select="round($ignoreCount * 200 div $total )"/>px</xsl:attribute> + </span> + </xsl:if> + <xsl:if test="round($failureCount * 200 div $total )!=0"> + <span class="uncovered"> + <xsl:attribute name="style">width:<xsl:value-of select="round($failureCount * 200 div $total )"/>px</xsl:attribute> + </span> + </xsl:if> + </td> + <td> + <xsl:call-template name="display-time"> + <xsl:with-param name="value" select="$timeCount"/> + </xsl:call-template> + </td> + </tr> + </table> + <span id=":i18n:Note">Note</span>: <i id=":i18n:failures">failures</i>\xA0<span id=":i18n:anticipated">are anticipated and checked for with assertions while</span>\xA0<i id=":i18n:errors">errors</i>\xA0<span id=":i18n:unanticipated">are unanticipated.</span> + </xsl:template> + +<!-- + ===================================================================== + testcase report + ===================================================================== +--> +<xsl:template match="test-case"> + <xsl:param name="summary.xml"/> + <xsl:param name="open.description"/> + + <xsl:variable name="summaries" select="document($summary.xml)"/> + + <xsl:variable name="Mname" select="concat('M:',./@name)"/> + + <xsl:variable name="result"> + <xsl:choose> + <xsl:when test="./failure"><span id=":i18n:Failure">Failure</span></xsl:when> + <xsl:when test="./error"><span id=":i18n:Error">Error</span></xsl:when> + <xsl:when test="@executed='False'"><span id=":i18n:Ignored">Ignored</span></xsl:when> + <xsl:otherwise><span id=":i18n:Pass">Pass</span></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> + + <td width="20%"> + <xsl:choose> + <xsl:when test="$summary.xml != ''"> + <!-- Triangle image --> + <a title="Show/Hide XML Comment" class="summarie"><xsl:attribute name="href">javascript:Toggle('<xsl:value-of select="concat('M:',$newid)"/>');ToggleImage('<xsl:value-of select="concat('I:',$newid)"/>')</xsl:attribute><xsl:attribute name="id"><xsl:value-of select="concat('I:',$newid)"/></xsl:attribute> + <!-- Set the good triangle image 6/4 font-family:Webdings--> + <xsl:choose> + <xsl:when test="$result != "Pass"">-</xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="$open.description='yes'">-</xsl:when> + <xsl:otherwise>+</xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + </a> + </xsl:when> + </xsl:choose> + <!-- If failure, add click on the test method name and color red --> + <xsl:choose> + <xsl:when test="$result = 'Failure' or $result = 'Error'">\xA0<a title="Show/Hide message error"> + <xsl:attribute name="href">javascript:Toggle('<xsl:value-of select="$newid"/>')</xsl:attribute> + <xsl:attribute name="class">error</xsl:attribute> + <xsl:value-of select="nunit2report:TestCaseName(./@name)"/> + </a> + </xsl:when> + <xsl:when test="$result = 'Ignored'">\xA0<a title="Show/Hide message error"> + <xsl:attribute name="href">javascript:Toggle('<xsl:value-of select="$newid"/>')</xsl:attribute> + <xsl:attribute name="class">ignored</xsl:attribute> + <xsl:value-of select="nunit2report:TestCaseName(./@name)"/> + </a> + </xsl:when> + <xsl:otherwise> + <xsl:attribute name="class">method</xsl:attribute>\xA0<xsl:value-of select="nunit2report:TestCaseName(./@name)"/> + </xsl:otherwise> + </xsl:choose> + </td> + <td width="65%" style="padding-left:3px" height="9px"> + <xsl:choose> + <xsl:when test="$result = 'Pass'"> + <span class="covered" style="width:200px"/> + </xsl:when> + <xsl:when test="$result = 'Ignored'"> + <span class="ignored" style="width:200px"/> + </xsl:when> + <xsl:when test="$result = 'Failure' or $result = 'Error'"> + <span class="uncovered" style="width:200px"/> + </xsl:when> + </xsl:choose> + <!-- The test method description--> + <xsl:choose> + <xsl:when test="$summary.xml != ''"> + <div class="description" style="display:block"> + <!-- Attribute id --> + <xsl:attribute name="id"><xsl:value-of select="concat('M:',$newid)"/></xsl:attribute> + <!-- Open method description if failure --> + <xsl:choose> + <xsl:when test="$result != "Pass""> + <xsl:attribute name="style">display:block</xsl:attribute> + </xsl:when> + <xsl:otherwise> + <xsl:choose> + <xsl:when test="$open.description = 'yes'"> + <xsl:attribute name="style">display:block</xsl:attribute> + </xsl:when> + <xsl:otherwise> + <xsl:attribute name="style">display:none</xsl:attribute> + </xsl:otherwise> + </xsl:choose> + </xsl:otherwise> + </xsl:choose> + <!-- The description of the test method --> + <xsl:value-of select="normalize-space($summaries//member[@name=$Mname]/summary/text())"/> + </div> + </xsl:when> + </xsl:choose> + </td> + <td><xsl:attribute name="id">:i18n:<xsl:value-of select="$result"/></xsl:attribute><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="4" class="FailureDetail"> + <xsl:apply-templates select="./failure"/> + <xsl:apply-templates select="./error"/> + <xsl:apply-templates select="./reason"/> + </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> --> + +<!-- Style for the error and failure in the tescase 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 --> +<!-- <code> + <p/> + <xsl:call-template name="br-replace"> + <xsl:with-param name="word" select="."/> + </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"/> + <h2 id=":i18n:EnvironmentInformation">Environment Information</h2> + <table border="0" cellpadding="5" cellspacing="2" width="95%"> + <tr class="TableHeader"> + <td id=":i18n:Property">Property</td> + <td id=":i18n:Value">Value</td> + </tr> + <tr> + <td id=":i18n:NAntLocation">NAnt Location</td> + <td><xsl:value-of select="$nant.filename"/></td> + </tr> + <tr> + <td id=":i18n:NAntVersion">NAnt Version</td> + <td><xsl:value-of select="$nant.version"/></td> + </tr> + <tr> + <td id=":i18n:Buildfile">Buildfile</td> + <td><xsl:value-of select="$nant.project.buildfile"/></td> + </tr> + <tr> + <td id=":i18n:BaseDirectory">Base Directory</td> + <td><xsl:value-of select="$nant.project.basedir"/></td> + </tr> + <tr> + <td id=":i18n:OperatingSystem">Operating System</td> + <td><xsl:value-of select="$sys.os"/></td> + </tr> + <tr> + <td id=":i18n:NETCLRVersion">.NET CLR Version</td> + <td><xsl:value-of select="$sys.clr.version"/></td> + </tr> + </table> + <a href="#top" id=":i18n:Backtotop">Back to top</a> +</xsl:template> + +<!-- I am sure that all nodes are called --> +<xsl:template match="*"> + <xsl:apply-templates/> +</xsl:template> + +</xsl:stylesheet> \ No newline at end of file Property changes on: trunk/xmlunit/lib/toolkit.xsl ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java 2010-06-21 09:02:59 UTC (rev 403) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DOMDifferenceEngine.java 2010-06-21 14:37:51 UTC (rev 404) @@ -16,6 +16,7 @@ import net.sf.xmlunit.util.Convert; import javax.xml.transform.Source; import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import org.w3c.dom.Document; /** @@ -74,7 +75,54 @@ compareNodes(Convert.toNode(control), Convert.toNode(test)); } - private ComparisonResult compareNodes(Node control, Node test) { + /** + * Recursively compares two XML nodes. + * + * <p>Performs comparisons common to all node types, the performs + * the node type specific comparisons and finally recures into + * the node's child lists.</p> + * + * <p>Stops as soon as any comparison returns + * ComparisonResult.CRITICAL.</p> + * + * <p>package private to support tests.</p> + */ + ComparisonResult compareNodes(Node control, Node test) { + ComparisonResult lastResult = + compare(new Comparison(ComparisonType.NODE_TYPE, control, + null, control.getNodeType(), + test, null, test.getNodeType())); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + lastResult = + compare(new Comparison(ComparisonType.NAMESPACE_URI, control, + null, control.getNamespaceURI(), + test, null, test.getNamespaceURI())); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + lastResult = + compare(new Comparison(ComparisonType.NAMESPACE_PREFIX, control, + null, control.getPrefix(), + test, null, test.getPrefix())); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + NodeList controlChildren = control.getChildNodes(); + NodeList testChildren = test.getChildNodes(); + lastResult = + compare(new Comparison(ComparisonType.CHILD_NODELIST_LENGTH, + control, null, controlChildren.getLength(), + test, null, testChildren.getLength())); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + /* TODO node type specific stuff */ + return compareNodeLists(controlChildren, testChildren); + } + + ComparisonResult compareNodeLists(NodeList control, NodeList test) { return ComparisonResult.EQUAL; } Modified: trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DifferenceEvaluators.java =================================================================== --- trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DifferenceEvaluators.java 2010-06-21 09:02:59 UTC (rev 403) +++ trunk/xmlunit/src/main/java-core/net/sf/xmlunit/diff/DifferenceEvaluators.java 2010-06-21 14:37:51 UTC (rev 404) @@ -67,7 +67,7 @@ * evaluator to decide which differences leave the documents * simlar. */ - public static final DifferenceEvaluator defaultStopWhenDifferent + public static final DifferenceEvaluator DefaultStopWhenDifferent = stopWhenDifferent(Default); /** Modified: trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs =================================================================== --- trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs 2010-06-21 09:02:59 UTC (rev 403) +++ trunk/xmlunit/src/main/net-core/diff/DOMDifferenceEngine.cs 2010-06-21 14:37:51 UTC (rev 404) @@ -57,7 +57,53 @@ net.sf.xmlunit.util.Convert.ToNode(test)); } - private ComparisonResult CompareNodes(XmlNode control, XmlNode test) { + /// <summary> + /// Recursively compares two XML nodes. + /// </summary> + /// <remarks> + /// Performs comparisons common to all node types, the performs + /// the node type specific comparisons and finally recures into + /// the node's child lists. + /// + /// Stops as soon as any comparison returns ComparisonResult.CRITICAL. + /// </remarks> + internal ComparisonResult CompareNodes(XmlNode control, XmlNode test) { + ComparisonResult lastResult = + Compare(new Comparison(ComparisonType.NODE_TYPE, control, + null, control.NodeType, + test, null, test.NodeType)); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + lastResult = + Compare(new Comparison(ComparisonType.NAMESPACE_URI, control, + null, control.NamespaceURI, + test, null, test.NamespaceURI)); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + lastResult = + Compare(new Comparison(ComparisonType.NAMESPACE_PREFIX, control, + null, control.Prefix, + test, null, test.Prefix)); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + XmlNodeList controlChildren = control.ChildNodes; + XmlNodeList testChildren = test.ChildNodes; + lastResult = + Compare(new Comparison(ComparisonType.CHILD_NODELIST_LENGTH, + control, null, controlChildren.Count, + test, null, testChildren.Count)); + if (lastResult == ComparisonResult.CRITICAL) { + return lastResult; + } + /* TODO node type specific stuff */ + return CompareNodeLists(controlChildren, testChildren); + } + + ComparisonResult CompareNodeLists(XmlNodeList control, + XmlNodeList test) { return ComparisonResult.EQUAL; } Modified: trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java =================================================================== --- trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java 2010-06-21 09:02:59 UTC (rev 403) +++ trunk/xmlunit/src/tests/java-core/net/sf/xmlunit/diff/DOMDifferenceEngineTest.java 2010-06-21 14:37:51 UTC (rev 404) @@ -13,7 +13,12 @@ */ package net.sf.xmlunit.diff; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.junit.Before; import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Element; import static org.junit.Assert.*; public class DOMDifferenceEngineTest { @@ -111,4 +116,106 @@ null, null, new Short("2")))); assertEquals(1, l.getInvocations()); } + + private static class DiffExpecter implements ComparisonListener { + private int invoked = 0; + private final int expectedInvocations; + private final ComparisonType type; + private DiffExpecter(ComparisonType type) { + this(type, 1); + } + private DiffExpecter(ComparisonType type, int expected) { + this.type = type; + this.expectedInvocations = expected; + } + public void comparisonPerformed(Comparison comparison, + ComparisonResult outcome) { + assertTrue(invoked < expectedInvocations); + invoked++; + assertEquals(type, comparison.getType()); + assertEquals(ComparisonResult.CRITICAL, outcome); + } + } + + private Document doc; + + @Before public void createDoc() throws Exception { + doc = DocumentBuilderFactory.newInstance().newDocumentBuilder() + .newDocument(); + } + + @Test public void compareNodesOfDifferentType() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.NODE_TYPE); + d.addDifferenceListener(ex); + d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(doc.createElement("x"), + doc.createComment("x"))); + assertEquals(1, ex.invoked); + } + + @Test public void compareNodesWithoutNS() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.NODE_TYPE, 0); + d.addDifferenceListener(ex); + d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); + assertEquals(ComparisonResult.EQUAL, + d.compareNodes(doc.createElement("x"), + doc.createElement("x"))); + assertEquals(0, ex.invoked); + } + + @Test public void compareNodesDifferentNS() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.NAMESPACE_URI); + d.addDifferenceListener(ex); + d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(doc.createElementNS("x", "y"), + doc.createElementNS("z", "y"))); + assertEquals(1, ex.invoked); + } + + @Test public void compareNodesDifferentPrefix() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = new DiffExpecter(ComparisonType.NAMESPACE_PREFIX); + d.addDifferenceListener(ex); + d.setDifferenceEvaluator(new DifferenceEvaluator() { + public ComparisonResult evaluate(Comparison comparison, + ComparisonResult outcome) { + if (comparison.getType() + == ComparisonType.NAMESPACE_PREFIX) { + assertEquals(ComparisonResult.DIFFERENT, outcome); + return ComparisonResult.CRITICAL; + } + assertEquals(ComparisonResult.EQUAL, outcome); + return ComparisonResult.EQUAL; + } + }); + assertEquals(ComparisonResult.CRITICAL, + d.compareNodes(doc.createElementNS("x", "x:y"), + doc.createElementNS("x", "z:y"))); + assertEquals(1, ex.invoked); + } + + @Test public void compareNodesDifferentNumberOfChildren() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + DiffExpecter ex = + new DiffExpecter(ComparisonType.CHILD_NODELIST_LENGTH, 2); + d.addDifferenceListener(ex); + d.setDifferenceEvaluator(DifferenceEvaluators.DefaultStopWhenDifferent); + Element e1 = doc.createElement("x"); + Element e2 = doc.createElement("x"); + assertEquals(ComparisonResult.EQUAL, d.compareNodes(e1, e2)); + e1.appendChild(doc.createElement("x")); + assertEquals(ComparisonResult.CRITICAL, d.compareNodes(e1, e2)); + assertEquals(1, ex.invoked); + e2.appendChild(doc.createElement("x")); + assertEquals(ComparisonResult.EQUAL, d.compareNodes(e1, e2)); + e2.appendChild(doc.createElement("x")); + assertEquals(ComparisonResult.CRITICAL, d.compareNodes(e1, e2)); + assertEquals(2, ex.invoked); + } + } Modified: trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs =================================================================== --- trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs 2010-06-21 09:02:59 UTC (rev 403) +++ trunk/xmlunit/src/tests/net-core/diff/DOMDifferenceEngineTest.cs 2010-06-21 14:37:51 UTC (rev 404) @@ -12,6 +12,7 @@ limitations under the License. */ using System; +using System.Xml; using NUnit.Framework; namespace net.sf.xmlunit.diff { @@ -124,5 +125,117 @@ Convert.ToInt16("2")))); Assert.AreEqual(1, invocations); } + + private XmlDocument doc; + + [SetUp] + public void CreateDoc() { + doc = new XmlDocument(); + } + + [Test] + public void CompareNodesOfDifferentType() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + int invocations = 0; + d.DifferenceListener += delegate(Comparison comp, + ComparisonResult r) { + Assert.AreEqual(0, invocations); + invocations++; + Assert.AreEqual(ComparisonType.NODE_TYPE, comp.Type); + Assert.AreEqual(ComparisonResult.CRITICAL, r); + }; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + Assert.AreEqual(ComparisonResult.CRITICAL, + d.CompareNodes(doc.CreateElement("x"), + doc.CreateComment("x"))); + Assert.AreEqual(1, invocations); + } + + [Test] + public void CompareNodesWithoutNS() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + d.DifferenceListener += delegate(Comparison comp, + ComparisonResult r) { + Assert.Fail("unexpected invocation"); + }; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + Assert.AreEqual(ComparisonResult.EQUAL, + d.CompareNodes(doc.CreateElement("x"), + doc.CreateElement("x"))); + } + + [Test] + public void CompareNodesDifferentNS() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + int invocations = 0; + d.DifferenceListener += delegate(Comparison comp, + ComparisonResult r) { + Assert.AreEqual(0, invocations); + invocations++; + Assert.AreEqual(ComparisonType.NAMESPACE_URI, comp.Type); + Assert.AreEqual(ComparisonResult.CRITICAL, r); + }; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + Assert.AreEqual(ComparisonResult.CRITICAL, + d.CompareNodes(doc.CreateElement("y", "x"), + doc.CreateElement("y", "z"))); + Assert.AreEqual(1, invocations); + } + + [Test] + public void CompareNodesDifferentPrefix() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + int invocations = 0; + d.DifferenceListener += delegate(Comparison comp, + ComparisonResult r) { + Assert.AreEqual(0, invocations); + invocations++; + Assert.AreEqual(ComparisonType.NAMESPACE_PREFIX, comp.Type); + Assert.AreEqual(ComparisonResult.CRITICAL, r); + }; + d.DifferenceEvaluator = delegate(Comparison comparison, + ComparisonResult outcome) { + if (comparison.Type == ComparisonType.NAMESPACE_PREFIX) { + Assert.AreEqual(ComparisonResult.DIFFERENT, outcome); + return ComparisonResult.CRITICAL; + } + Assert.AreEqual(ComparisonResult.EQUAL, outcome); + return ComparisonResult.EQUAL; + }; + Assert.AreEqual(ComparisonResult.CRITICAL, + d.CompareNodes(doc.CreateElement("x:y", "x"), + doc.CreateElement("z:y", "x"))); + Assert.AreEqual(1, invocations); + } + + [Test] + public void CompareNodesDifferentNumberOfChildren() { + DOMDifferenceEngine d = new DOMDifferenceEngine(); + int invocations = 0; + d.DifferenceListener += delegate(Comparison comp, + ComparisonResult r) { + Assert.Greater(2, invocations); + invocations++; + Assert.AreEqual(ComparisonType.CHILD_NODELIST_LENGTH, + comp.Type); + Assert.AreEqual(ComparisonResult.CRITICAL, r); + }; + d.DifferenceEvaluator = + DifferenceEvaluators.DefaultStopWhenDifferent; + XmlElement e1 = doc.CreateElement("x"); + XmlElement e2 = doc.CreateElement("x"); + Assert.AreEqual(ComparisonResult.EQUAL, d.CompareNodes(e1, e2)); + e1.AppendChild(doc.CreateElement("x")); + Assert.AreEqual(ComparisonResult.CRITICAL, d.CompareNodes(e1, e2)); + Assert.AreEqual(1, invocations); + e2.AppendChild(doc.CreateElement("x")); + Assert.AreEqual(ComparisonResult.EQUAL, d.CompareNodes(e1, e2)); + e2.AppendChild(doc.CreateElement("x")); + Assert.AreEqual(ComparisonResult.CRITICAL, d.CompareNodes(e1, e2)); + Assert.AreEqual(2, invocations); + } } } Modified: trunk/xmlunit/xmlunit.nant.build =================================================================== --- trunk/xmlunit/xmlunit.nant.build 2010-06-21 09:02:59 UTC (rev 403) +++ trunk/xmlunit/xmlunit.nant.build 2010-06-21 14:37:51 UTC (rev 404) @@ -25,6 +25,7 @@ <property name="gen.src.dir" value="${base.dir}/build/generated/net" overwrite="false"/> <property name="build.dir" value="${base.dir}/build/net" overwrite="false"/> + <property name="test.report.dir" value="${build.dir}/test-report"/> <property name="bin.dir" value="${build.dir}/bin" overwrite="false"/> <property name="csc.verbose" value="false" overwrite="false"/> @@ -99,8 +100,12 @@ <target name="test" description="run all tests" depends="compile"> <nunit2> <formatter type="Plain"/> + <formatter type="Xml" usefile="true" outputdir="${test.report.dir}"/> <test assemblyname="${bin.dir}/${project::get-name()}-core.tests.dll"/> </nunit2> + <style style="lib/NUnitSummary.xsl" + in="${test.report.dir}/${project::get-name()}-core.tests.dll-results" + out="${test.report.dir}/html/index.html"/> </target> <target name="deploy" description="zip all code for deployment" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |