与 :| 发生 && 短路在 ScalaCheck 的表达式中
Have && short circuit with :| in expressions in ScalaCheck
我正在尝试在 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)
但是,当我包含带有 :|
的失败消息时,它失败并在 value.sameElements(decoded.get)
行显示 NoSuchElementException
,并且不显示 decoded.isDefined
的失败消息即使它的计算结果为 false。
我使用的导入和测试 class 声明如下:
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
}
)
}
是否有任何方法可以使 &&
短路以使用 :|
处理表达式,或者是否有解决此问题的方法?
为什么你看到了差异
问题在于,布尔值的 &&
是短路的,而 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))
)
(值得一提的是 的另一个例子。)
解决方法
不幸的是,不可能在 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 模块中)”,所以如果你发现你经常做这种事情,你可以尝试打开一个拉取请求以将方法从 Commands
到 Prop
并使其成为 public.
不过,在你在这里给出的具体情况下,我可能建议在 Option
上使用类似 exists
的东西,而不是检查它是否已定义,然后使用 get
.
我正在尝试在 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)
但是,当我包含带有 :|
的失败消息时,它失败并在 value.sameElements(decoded.get)
行显示 NoSuchElementException
,并且不显示 decoded.isDefined
的失败消息即使它的计算结果为 false。
我使用的导入和测试 class 声明如下:
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
}
)
}
是否有任何方法可以使 &&
短路以使用 :|
处理表达式,或者是否有解决此问题的方法?
为什么你看到了差异
问题在于,布尔值的 &&
是短路的,而 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))
)
(值得一提的是
解决方法
不幸的是,不可能在 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 模块中)”,所以如果你发现你经常做这种事情,你可以尝试打开一个拉取请求以将方法从 Commands
到 Prop
并使其成为 public.
不过,在你在这里给出的具体情况下,我可能建议在 Option
上使用类似 exists
的东西,而不是检查它是否已定义,然后使用 get
.