2010-11-23 10 views
12

私は2つのscala.xml.Elemオブジェクトを持っています(実際の、期待されています)。私はJUnit 4を使用していますが、XMLUnit 1.3も含んでいます。ユニットテストでscala.xml.Elemオブジェクトを比較します

2つのオブジェクトを比較して、XML内の属性の順序と無意味な空白を無視する簡単な方法はありますか?

私はXMLUnit.assertXMLEqual()を試しましたが、タイプがscala.xml.Elemであると訴えています。

私はequalsまたは==を使うことができると知っていますが、アサーションが2つの値を等しくない場合に出力する利点があります。 assertTrue(actual.equals(expected))を使用し、それらが等しくない場合、唯一の出力は「アサーションに失敗しました」です。

答えて

10

使用

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

私はassertTrueの使用を検討していました。私は 'diff'について知らなかった。私はそれを試みます。ありがとう。 – Ralph

14

は、必要に応じて等しくないdescendandノードの文字列を生成するために

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

と(例えば)diffをカスタムメッセージを渡すことができますassertTrueのバージョン空白を無視するXML Elemオブジェクトと比較するには、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 
あなたがXMLリテラルを使用する場合Scalaは属性の順序を気にしません

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 

私はユニットテストのためのScalaTestをお勧めしますが、あなたが持っている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

私は空白を切り取ることについてのフォローアップの質問を投稿しようとしていましたが、あなたの答えはそれをカバーしています。ありがとう。 – Ralph

1

以前の答えは私には有益でしたが、時にはXMLの大部分をチェックしたいと思っていましたが、XMLの両方のチャンクを示す失敗の比較はちょっと難しかった読む。このメソッドは、子要素を最初に子要素に再帰的に反復しようとします。したがって、深くネストされた要素が間違っていると、はるかに簡潔なエラーが表示されます。あなたのXMLによっては、実際にどこが失敗しているのかを十分に把握することができないかもしれませんが、私はそれが有用であると感じています。

/** 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)) 

} 
関連する問題