2010-11-23 5 views
12

J'ai deux objets scala.xml.Elem (réels, attendus). J'utilise JUnit 4, mais j'ai aussi inclus XMLUnit 1.3.Comparer objet scala.xml.Elem en test unitaire

Existe-t-il un moyen facile de comparer les deux objets pour l'égalité, en ignorant l'ordre des attributs et les espaces insignifiants dans le XML? J'ai essayé XMLUnit.assertXMLEqual(), mais il se plaint que les types sont scala.xml.Elem.

Je sais que je peux utiliser equals ou ==, mais je voudrais l'avantage d'avoir l'assertion d'imprimer les deux valeurs quand elles ne sont pas égales. Si j'utilise assertTrue(actual.equals(expected)) et qu'ils ne sont pas égaux, la seule sortie sera "assertion failed".

Répondre

10

Utilisez la version de assertTrue qui permet de passer des messages personnalisés

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

et (par exemple) diff pour produire la chaîne avec les noeuds de descendand qui ne sont pas égaux

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>) 
+0

J'avais envisagé d'utiliser assertTrue. Je ne connaissais pas 'diff'. Je vais essayer ça. Merci. – Ralph

14

Si vous voulez pour comparer à des objets XML Elem ignorant les espaces, vous pouvez en retirer les espaces blancs avec la méthode scala.xml.Utility.trim.

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 ne se soucie pas de l'ordre des attributs si vous utilisez XML littéraux:

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 

Je recommande ScalaTest pour les tests unitaires là, vous avez le 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... 
+0

J'allais poster une question de suivi sur les espaces de coupe, mais votre réponse couvre cela. Merci. – Ralph

1

Les réponses précédentes m'ont été utiles, même si je me suis rendu compte que parfois je voulais vérifier un plus gros morceau de XML et la comparaison des échecs montrant les deux parties de XML était un peu difficile lire. Cette méthode va essayer de se recomposer en éléments enfants d'abord pour les comparer, donc si un élément profondément imbriqué est incorrect, il montrera une erreur beaucoup plus concise. En fonction de votre XML, cela ne vous donnera peut-être pas assez de contexte pour déterminer où il échoue réellement, mais je le trouve utile.

/** Check that the XMLs are the same, ignoring empty text nodes (whitespace). */ 
private def assertEqual(actual: xml.Node, expected: xml.Node) { 

    def recurse(actual: xml.Node, expected: xml.Node) { 
     // depth-first checks, to get specific failures 
     for ((actualChild, expectedChild) <- actual.child zip expected.child) { 
      recurse(actualChild, expectedChild) 
     } 
     actual should be (expected) 
    } 

    recurse(scala.xml.Utility.trim(actual), scala.xml.Utility.trim(expected)) 

}