Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare scala.xml.Elem object in unit test

Tags:

junit

xml

scala

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 objects for equality, ignoring attribute order and insignificant whitespace in the XML?

I tried XMLUnit.assertXMLEqual(), but it complains that the types are scala.xml.Elem.

I know that I can use equals or ==, but I would like the benefit of having the assertion print the two values when they are not equal. If I use assertTrue(actual.equals(expected)), and they are not equal, the only output will be "assertion failed".

like image 358
Ralph Avatar asked Nov 23 '10 21:11

Ralph


2 Answers

If you want to compare to XML Elem objects ignoring whitespaces you can remove the whitespaces from them with scala.xml.Utility.trim method.

scala> val a = <foo>bar</foo>
a: scala.xml.Elem = <foo>bar</foo>

scala> val b = <foo>   bar   </foo>
b: scala.xml.Elem = <foo>   bar   </foo>

scala> a == b
res8: Boolean = false

scala> import scala.xml.Utility.trim
import scala.xml.Utility.trim

scala> trim(a) == trim(b)
res9: Boolean = true

Scala does not care about the order of the attributes if you use XML literals:

scala> val a = <foo first="1" second="2" />
a: scala.xml.Elem = <foo first="1" second="2"></foo>

scala> val b = <foo second="1" first="1"  />
b: scala.xml.Elem = <foo first="1" second="1"></foo>

scala> a == b
res22: Boolean = true

I would recommend ScalaTest for unit testing there you have the ShouldMatchers:

// Scala repl started with scalatest-1.2.jar in the classpath

scala> val a = <foo>bar</foo>
a: scala.xml.Elem = <foo>bar</foo>

scala> val b = <foo>bar</foo>
b: scala.xml.Elem = <foo>bar</foo>

scala> a should equal(b)

scala> val b = <foo>bar2</foo>
b: scala.xml.Elem = <foo>bar2</foo>

scala> a should equal(b)
org.scalatest.TestFailedException: <foo>bar</foo> did not equal <foo>bar2</foo>
    at org.scalatest.matchers.Matchers$class.newTestFailedException(Matchers.scala:148)
    at org.scalatest.matchers.ShouldMatchers$.newTestFailedException(ShouldMatchers.scala:2329)
    at org.scalatest.matchers.ShouldMatchers$ShouldMethodHelper$.shouldMatcher(ShouldMatchers.scala:871)
    at org.scalatest.matchers.ShouldMatchers$SeqShouldWrapper.should(ShouldMatchers.scala:1724)
    at .<init>(<console>:15)
    at .<clinit>(<console>)
    at RequestResult$.<init>(<console>:9)
    at RequestResult$.<clinit>(<console>)
    at RequestResult$scala_repl_result(<console>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.Delega...
like image 146
michael.kebe Avatar answered Oct 25 '22 07:10

michael.kebe


Use the version of assertTrue that allows passing custom messages

public static void assertTrue(java.lang.String message,
                              boolean condition)

and (for example) diff to produce the string with the descendand nodes that aren't equal

scala> val xml1 = <person><name>john</name><lastname>smith</lastname></person>
xml1: scala.xml.Elem = <person><name>john</name><lastname>smith</lastname></person>

scala> val xml2 = <person><name>jane</name><lastname>smith</lastname></person>
xml2: scala.xml.Elem = <person><name>jane</name><lastname>smith</lastname></person>

scala> assert(xml1 == xml2, xml1.child diff xml2.child mkString(", "))
java.lang.AssertionError: assertion failed: <name>john</name>
        at scala.Predef$.assert(Predef.scala:91)
        at .<init>(<console>:8)
        at .<clinit>(<console>)
like image 29
Vasil Remeniuk Avatar answered Oct 25 '22 06:10

Vasil Remeniuk