Избегание поведения Scala XML <a>b {"c"} </a>! = <a>b c </a> в тестах - PullRequest
2 голосов
/ 18 ноября 2011

Я использую самое большое и хочу сказать

actualXML should be === expectedXML

особенно потому, что === не заботится о порядке атрибутов. Однако утверждение не выполняется, если текст был внедрен с использованием синтаксиса {...} XML Scala, поскольку

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

но хотел бы иметь возможность использовать ванильный синтаксис.

Ответы [ 2 ]

2 голосов
/ 18 ноября 2011

Вы можете ввести свой собственный класс эквалайзера специально для Xml Elem:

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, которое сравнивает отмытые элементы.

1 голос
/ 19 ноября 2011

Смотрите ответ выше - теперь я лучше понимаю область.Вот код с исправленными скобками и тест, основанный на комментариях Мэтью и Дейва.

Мои извинения за его размер:

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

}
...