如何重写某些生成器以使ScalaCheck强制(自动)生成精炼类型?仅非空列表,例如

时间:2019-03-28 13:34:07

标签: scala scalacheck property-based-testing

我有一个很大的案例类结构,并且在这个结构的深处,我有一些要优化的字段,例如,使列表为非空。是否可以告诉ScalaCheck使用scalacheck-magnolia项目的自动派生使那些列表为非空(而无需专门提供每个字段)? 示例:

import com.mrdziuban.ScalacheckMagnolia.deriveArbitrary
import org.scalacheck.Arbitrary
import org.scalacheck.Gen

case class A(b: B, c: C)
case class B(list: List[Long])
case class C(list: List[Long])

// I've tried:
def genNEL[T: Gen]: Gen[List[T]] = Gen.nonEmptyListOf(implicitly[Gen[T]])
implicit val deriveNEL = Arbitrary(genNEL)

implicit val deriveA = implicitly[Arbitrary[A]](deriveArbitrary)

但是还没有解决。

1 个答案:

答案 0 :(得分:1)

我不确定如何通用,因为我不熟悉使用scalacheck-magnolia自动获取Arbitrary的方法。似乎scalacheck-magnolia非常适合为案例类派生Arbitrary,但可能不适用于容器(列表,向量,数组等)。

如果您只想使用普通的ScalaCheck,则可以自己为Arbitrary定义隐式A。手工执行此操作会增加一些额外的样板,但是这样做的好处是,如果您想对数据结构的不同部分使用不同的生成器,那么您将拥有更多的控制权。

下面是一个示例,其中Arbitrary的long列表默认情况下为非空,但对于B为空。

implicit val listOfLong =
  Arbitrary(Gen.nonEmptyListOf(Arbitrary.arbitrary[Long]))


implicit val arbC = Arbitrary {
  Gen.resultOf(C)
}

implicit val arbB = Arbitrary {
  implicit val listOfLong =
    Arbitrary(Gen.listOf(Arbitrary.arbitrary[Long]))
  Gen.resultOf(B)
}

implicit val arbA = Arbitrary {
  Gen.resultOf(A)
}

property("arbitrary[A]") = {
  Prop.forAll { a: A =>
    a.b.list.size >= 0 && a.c.list.size > 0
  }
}