Использование сопоставителя содержит списки Scala в тесте Scala

Я пытаюсь проверить, что список классов case содержит конкретный экземпляр одного из них, однако, когда я пытаюсь это сделать, я получаю следующую ошибку:

[info] Compiling 1 Scala source to /home/matt/Documents/transledge/app/target/scala-2.9.2/test-classes...
[error] /home/matt/Documents/transledge/app/src/test/scala/com/transledge/drewes/parser_suite.scala:40: overloaded method value should with alternatives:
[error]   (notWord: ParserSuite.this.NotWord)ParserSuite.this.ResultOfNotWordForSeq[com.transledge.Instruction,List[com.transledge.Instruction]] <and>
[error]   (haveWord: ParserSuite.this.HaveWord)ParserSuite.this.ResultOfHaveWordForSeq[com.transledge.Instruction] <and>
[error]   (beWord: ParserSuite.this.BeWord)ParserSuite.this.ResultOfBeWordForAnyRef[List[com.transledge.Instruction]] <and>
[error]   (rightMatcher: org.scalatest.matchers.Matcher[List[com.transledge.Instruction]])Unit
[error]  cannot be applied to (org.scalatest.matchers.Matcher[Traversable[com.transledge.AddNode]])
[error]       parsing(square_node, input) should contain(AddNode("foo"))
[error]                                   ^
[error] one error found
[error] (test:compile) Compilation failed
[error] Total time: 3 s, completed 21-Feb-2013 15:15:04

Рассматриваемый набор тестов:

import org.scalatest.FunSpec
import scala.util.parsing.combinator._
import com.transledge.drewes.{Parser => DrewesParser}
import com.transledge._
import org.scalatest.matchers.ShouldMatchers

class ParserSuite extends DrewesParser with FunSpec with ShouldMatchers {

  def parsing[A](parser: Parser[A], input: String): A = parse(parser, input).get

  // snipping other tests

  describe("square_node") {
    val input = """\squarenode{foo}(1cm, 2cm)"""
    it("should create a node") {
      parsing(square_node, input) should contain(AddNode("foo")) // Line 40
    }
  }
}

Определение AddNode/Instruction довольно простое:

package com.transledge

abstract class Instruction
case class AddNode(id: String) extends Instruction

А вот урезанное определение парсера:

package com.transledge.drewes
import scala.util.parsing.combinator._
import com.transledge._

trait Parser extends RegexParsers {
  def node_id: Parser[String] = "[a-zA-Z\\-_:0-9]+".r
  def node_name: Parser[String] = ("{" ~> node_id <~ "}") | node_id

  def point: Parser[String] = "[^,()]+".r
  def position: Parser[(String, String)] = "(" ~> point ~ "," ~ point <~ ")" ^^ { case a ~ "," ~ b => (a.trim, b.trim) }

  def square_node: Parser[List[Instruction]] = "\\squarenode" ~> node_name ~ position ^^ { case name ~ position => List(AddNode(name)) }

}

Насколько я понимаю, компилятор Scala должен использовать вариант should(rightMatcher: Matcher[List[T]]), но получает экземпляр Traversable вместо List, а поскольку Traversable является чертой, включаемой в List, Traversable нельзя использовать в месте, где List ожидал.

Итак, как мне проверить, что список содержит элемент?


person Matt    schedule 21.02.2013    source источник


Ответы (1)


Это упрощенная картина того, как это реализовано:

trait Matcher[T]

implicit class ListShouldWrapper[T](a:List[T]) {
  def should(rightMatcher: Matcher[List[T]]): Unit = ???
}

object contain {
  def apply[T](expectedElement: T): Matcher[GenTraversable[T]] = ???
}

Если вы протестируете эту реализацию с помощью:

val x:List[Int] = ???
x should contain(3)

Вы получите сообщение об ошибке компиляции, сообщающее, что GenTraversable найдено, а List требуется. Реализация могла бы работать лучше, если бы мы реализовали ее примерно следующим образом. Обратите внимание, что это не фактическое решение, поскольку это всего лишь изолированный фрагмент кода.

trait Matcher[T]

implicit class AnyToShould[T](a: T) {
  def should(a: Matcher[T]) = ???
}

def contain[C[_] <: Traversable[_], T](x:T):Matcher[C[T]] = ???

Проблема решаема, поэтому я предлагаю вам написать об ошибке (возможно, даже создать патч самостоятельно). Чтобы продолжить сейчас, у вас есть несколько вариантов:

  • Измените тип возврата def square_node: Parser[List[Instruction]]
  • Предоставьте метод contain самостоятельно, который возвращает «правильный» тип Matcher
  • Используйте другую библиотеку спецификаций Scala
person EECOLOR    schedule 21.02.2013