升级到 scalacheck 1.13.3
后,我遇到了一个奇怪的问题,即派生 A => B Or C
的实例,其中 Or
本质上是一个轻量级的 Either
,几乎总是会失败。
这是我可以编写的最简单的代码来重现该问题:
import org.scalatest.FunSuite
import org.scalatest.prop.GeneratorDrivenPropertyChecks
import org.scalacheck.Shapeless._
class Testor extends FunSuite with GeneratorDrivenPropertyChecks {
sealed trait Or[+A, +B] extends Product with Serializable
case class Left[A](a: A) extends Or[A, Nothing]
case class Right[B](b: B) extends Or[Nothing, B]
test("reproduce") {
forAll { (i: Int, f: Int ⇒ Float Or Boolean) ⇒
f(i)
}
}
}
这失败了:
RetrievalError was thrown during property evaluation.
Message: couldn't generate value
Occurred when passed generated values (
arg0 = 0, // 30 shrinks
arg1 = <function1>
)
请注意,提供明确的
Arbitrary[Float Or Boolean]
可以解决该问题,因此问题很明显出在泛型推导中。我不相信问题出在
shapeless-scalacheck
- 我尝试编写自己的通用派生来看看它是否有帮助,但它以完全相同的方式失败了。奇怪的是,这可能是由于任意函数的工作方式,函数实际上是生成的,但在评估时失败。
感谢您对此的任何帮助/建议,因为我有点卡住了。
最佳答案
问题在这里似乎是两方面的:
org.scalacheck.Test.Parameters.default
) 和 scalatest 中的默认测试参数,有一个 minSize
的 0
。 Prop.check
尝试在启动时生成具有此大小的值。 MkCoproductArbitrary.ccons
在生成任意联积时将大小为零解释为终止条件,因此失败。 作为临时解决方法,在 Travis 响应的示例中,可以通过以下方式检查该属性:
prop.check(Test.Parameters.default.withMinSize(1))
使用问题中使用的 scalatest,也可以更改 min size 参数,可能通过放置类似的内容
implicit val config = PropertyCheckConfiguration(minSize = PosZInt(1))
在测试用例之前(警告:我没有尝试/检查 scalatest 解决方案,与之前的纯 scalacheck 不同)。