2013-02-21 59 views
3

我试图检查的情况下类的列表中包含一个特定实例,但是当我尝试这样做,我得到以下错误:使用“包含”斯卡拉匹配Scala中测试列表

[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,并作为TraversableList包括的特征,Traversable不能用于List预计的地方。

那么如何检查列表中是否包含元素?

回答

6

这是它是如何实现的简化图:

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]] = ??? 

这个问题是可以解决的,所以我建议你提交一个bug(甚至可能自己创建一个补丁)。为了能够现在继续,你有几个选择:

  • 变化def square_node: Parser[List[Instruction]]
  • 供应contain方法自己的返回类型,返回“正确”类型的Matcher
  • 使用另一个斯卡拉规范库