升级到 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 - 我尝试编写自己的通用派生来看看它是否有帮助,但它以完全相同的方式失败了。

奇怪的是,这可能是由于任意函数的工作方式,函数实际上是生成的,但在评估时失败。

感谢您对此的任何帮助/建议,因为我有点卡住了。

最佳答案

问题在这里似乎是两方面的:

  • scalacheck ( org.scalacheck.Test.Parameters.default ) 和 scalatest 中的默认测试参数,有一个 minSize0Prop.check 尝试在启动时生成具有此大小的值。
  • scalacheck-shapeless 中的
  • MkCoproductArbitrary.ccons 在生成任意联积时将大小为零解释为终止条件,因此失败。

  • 作为临时解决方法,在 Travis 响应的示例中,可以通过以下方式检查该属性:
    prop.check(Test.Parameters.default.withMinSize(1))
    

    使用问题中使用的 scalatest,也可以更改 min size 参数,可能通过放置类似的内容
    implicit val config = PropertyCheckConfiguration(minSize = PosZInt(1))
    

    在测试用例之前(警告:我没有尝试/检查 scalatest 解决方案,与之前的纯 scalacheck 不同)。

    10-08 09:34