我正在尝试在Scala Test FlatSpec中创建一个基于属性的测试,该测试使用ScalaCheck :|
运算符为结束布尔表达式的不同部分提供失败消息。
但是,我遇到了&&
运算符不会短路的问题。在这种情况下,表达式的早期部分会检查表达式的下一部分是否可以运行,否则后面的部分会抛出异常。
以下是问题的示例。如果decoded
为None
,则表达式应该在&&
上短路,以便decoded.get
不会运行,因为它会引发异常。
val value: Array[Int] = Array.fill(2)(0)
val encoded = encode(value)
val decoded: Option[Array[Int]] = decode(value)
decoded.isDefined :| "decoded None" &&
value.sameElements(decoded.get)
当我在不使用:|
运算符的情况下编写布尔值来给出失败消息时,decoded.isDefined
上的测试失败而没有抛出异常。
val value: Array[Int] = Array.fill(2)(0)
val encoded = encode(value)
val decoded: Option[Array[Int]] = decode(value)
decoded.isDefined &&
value.sameElements(decoded.get)
但是,当我在:|
中添加失败消息时,NoSuchElementException
行上的value.sameElements(decoded.get)
失败,并且decoded.isDefined
没有显示失败消息它会评估为假。
我使用的导入和测试类声明如下:
import org.scalacheck.Prop._
import org.scalatest.prop.Checkers
import org.scalatest.{FlatSpec, Matchers}
class ByteRWTests extends FlatSpec with Matchers with Checkers {
我正在以下列方式撰写财产检查:
it should "be equal" in {
check(
forAll { (int: Int) =>
int == int
}
)
}
有没有办法让&&
使用:|
来处理表达式,或者是否有针对此问题的解决方法?
答案 0 :(得分:1)
问题在于,虽然布尔值的&&
是短路的,但&&
上的Prop
方法不是,并且您是否使用标签确定隐含的位置从布尔值转换为Prop
。例如:
import org.scalacheck.Prop, Prop._
val value: Array[Int] = Array.fill(2)(0)
val decoded: Option[Array[Int]] = None
val p1: Prop = decoded.isDefined && value.sameElements(decoded.get)
val p2: Prop = decoded.isDefined :| "decoded None" && value.sameElements(decoded.get)
这里p1
定义了解这个:
Prop.propBoolean(decoded.isDefined && value.sameElements(decoded.get))
虽然p2
给出了这个:
(Prop.propBoolean(decoded.isDefined) :| "decoded None").&&(
Prop.propBoolean(value.sameElements(decoded.get))
)
(值得一提的是why I don't like fancy implicit-conversion-based DSLs的另一个例子。)
不幸的是,&&
上的Prop
方法无法在此处执行您想要的操作,但您可以定义自己的连接版本:
def propAnd(p1: => Prop, p2: => Prop) = p1.flatMap { r =>
if (r.success) Prop.secure(p2) else Prop(_ => r)
}
然后:
scala> propAnd(decoded.isDefined :| "decoded None" , value.sameElements(decoded.get))
res1: org.scalacheck.Prop = Prop
scala> .check
! Falsified after 0 passed tests.
> Labels of failing property:
decoded None
此方法实际存在于ScalaCheck中,但它是not part of the public API。对实现的评论确实注意到它“(可能应该在Prop模块中)”,所以如果你发现你做了很多这样的事情,你可能会尝试打开一个pull请求来从{{1转到Commands
并公开。
在你给出的具体案例中,我可能建议在Prop
上使用exists
之类的内容,而不是检查它是否已定义,然后使用Option
。