2

我正在使用 scalatest 并想说

actualXML should be === expectedXML

特别是因为 === 不关心属性顺序。但是,当使用 Scala XML 的 { ... } 语法嵌入文本时,断言失败,因为

scala> <a>b {"c"}</a>.child
res8: scala.xml.Node* = ArrayBuffer(b , c)

然而:

scala> <a>b c</a>.child
res9: scala.xml.Node* = ArrayBuffer(b c)

我可以写一个方法

import scala.xml.Elem
import scala.xml.XML
def launder(xml: Elem): Elem = XML.loadString(xml.toString)

给予

launder(actualXML) should be === expectedXML

但希望能够使用香草语法。

4

2 回答 2

2

您可以专门为 Xml Elem 引入您自己的 Equalizer 类:

class ElemEqualizer(left: scala.xml.Elem) {
  def ===(right: Any) = new Equalizer(launder(left).===(launder(right))
}
implicit def convertToElemEqualizer(left: scala.xml.Elem) = new ElemEqualizer(left)

@Test def foobar(): Unit = {
  val a = <a>b {"c"}</a>
  val b = <a>b c</a>

  assert(a === b)
}

因此,您要引入另一个隐式转换,但这次专门用于Elem比较洗过的 Elem。

于 2011-11-18T15:26:34.133 回答
1

请参阅上面的答案 - 我现在更好地了解该地区。这是修正了括号的代码,以及基于 Matthew 和 Dave 的评论的测试。

我为它的大小道歉:

// Tested with Scala 2.9.1

import org.junit.Test
import org.scalatest.Assertions._
import org.scalatest.TestFailedException
import scala.xml.Elem
import scala.xml.Node
import scala.xml.XML
import scala.xml.Utility

class TestEquals {

  val a = <a>b {"c"}</a>
  val b = <a>b c</a>

  @Test def defaultBehaviour {
    assert(a === a)
    assert(b === b)

    // _but_ this fails
    intercept[TestFailedException] { assert(a === b) } // i.e. a != b
  }

  // Add class & implicit to improve the behaviour
  class ElemEqualizer(left: Any) {
    private def launder(x: Any): Node = Utility.trim(x match {
      case xml: String => XML.loadString(xml)
      case xml: Elem => XML.loadString(xml.toString)
    })

    def ===(right: Any): Option[String] =
      new Equalizer(launder(left)).===(launder(right))
  }

  implicit def convertToElemEqualizer(left: Elem) = new ElemEqualizer(left)

  // Retest the behaviour with ElemEqualizer available
  @Test def betterBehaviour {
    assert(a === b)
    assert(a === "<a>b c</a>")  // works for 'right' string that's XML - see launder

    intercept[TestFailedException]
      { assert("<a>b c</a>" === a) } // but not this way round

    // attribute order doesn't matter
    assert(<a attr0="123" attr1="456"/> === <a attr1="456" attr0="123"/>)

    // fails if attribute values don't match - that's good
    intercept[TestFailedException]
      { assert(<a attr0="123" attr1="456"/> === <a attr1="456" attr0="xxx"/>) }

    // and again with 'right' as a string
    intercept[TestFailedException]
      { assert(<a attr0="123" attr1="456"/> === XML.loadString("<a attr1='456' attr0='xxx'/>")) }
  }

  @Test def xmlContainingText {
    // Here left and right wouldn't be equal without use of Utility.trim()
    val left = <a>
 <b>text</b>
</a>
    val right = <a><b>text</b></a>
    assert(left === right)
  }

}
于 2011-11-19T00:10:10.897 回答