I have two scala.xml.Elem
objects (actual, expected). I am using JUnit 4, but have also included XMLUnit 1.3.
Is there any easy way to compare the two objec
I modified @Nick's code to work with JDom2. In his code, because of how zip
works, if expectedXML
has trailing elements that are not in actualXML
, the test passes. I fixed that bug, and made the comparison of trailing elements optional:
trait XMLTest extends XMLSupport {
/** Verify that the XMLs are the same, regardless of attribute or element ordering and ignoring whitespace. */
def assertEqual(actual: Element, expected: Element, ignoreTrailingElements: Boolean=false): Assertion = {
// depth-first comparison
def recurse(actual: Element, expected: Element): Assertion = {
import scala.collection.JavaConverters._
val actualChildren: Seq[Element] = actual.getChildren.asScala.sortBy(_.getName)
val expectedChildren: Seq[Element] = expected.getChildren.asScala.sortBy(_.getName)
(actualChildren zip expectedChildren) foreach { case (actualChild, expectedChild) =>
recurse(actualChild, expectedChild)
}
actual.getName shouldEqual expected.getName
actual.getTextNormalize shouldEqual expected.getTextNormalize
actual.getAttributes.asScala.map(_.toString).sorted shouldEqual expected.getAttributes.asScala.map(_.toString).sorted
if (!ignoreTrailingElements && actualChildren.size < expectedChildren.size) {
val diff = expectedChildren.drop(actualChildren.size)
fail("Extra XML children found: " + prettyPrint(diff))
} else succeed
}
recurse(actual, expected)
}
}
I wrote this trait to mix into the test code:
trait XMLSupport {
import org.jdom2.output.{Format, XMLOutputter}
def prettyPrint(doc: Document): String = {
val xmlOutput = new XMLOutputter()
xmlOutput.setFormat(Format.getPrettyFormat)
xmlOutput.outputString(doc)
}
def prettyPrint(elements: Seq[Element]): String = {
import scala.collection.JavaConverters._
val xmlOutput = new XMLOutputter()
xmlOutput.setFormat(Format.getPrettyFormat)
xmlOutput.outputString(elements.asJava)
}
}
I invoked the test this way:
class XmlTest extends WordSpec with MustMatchers {
// test code here
assertEqual(actualXML.getRootElement, expectedXML.getRootElement, ignoreTrailingElements=true)
}