简体   繁体   English

如何覆盖 ScalaCheck 的一些生成器以强制(自动)生成精炼类型? 仅非空列表,例如

[英]How to override some generators for ScalaCheck to force to (automatically) generate refined types? Non empty lists only, for example

I have a quite big structure of case classes and somewhere deep inside this structure I have fields which I want to refine, for example, make lists non-empty.我有一个相当大的案例类结构,在这个结构的深处,我有一些字段,我想细化,例如,使列表非空。 Is it possible to tell ScalaCheck to make those lists non-empty using automatic derivation from scalacheck-magnolia project (without providing each field specifically)?是否可以告诉 ScalaCheck 使用来自scalacheck-magnolia项目的自动派生使这些列表非空(不具体提供每个字段)? Example:例子:

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)

But it's didn't worked out.但它没有解决。

I'm not sure how to be generic, since I'm not familiar with getting automatic derivation for Arbitrary with scalacheck-magnolia.我不确定如何通用,因为我不熟悉使用 scalacheck-magnolia 自动推导Arbitrary It seems like scalacheck-magnolia is good for deriving an Arbitrary for case classes, but maybe not for containers (lists, vectors, arrays, etc.).似乎 scalacheck-magnolia 适合为 case 类派生Arbitrary ,但可能不适用于容器(列表、向量、数组等)。

If you want to just use plain ScalaCheck, you could just define the implicit Arbitrary for A yourself.如果您只想使用普通的 ScalaCheck,您可以自己为A定义隐式Arbitrary Doing it by hand is some extra boilerplate, but it has the benefit that you have more control if you want to use different generators for different parts of your data structure.手动完成是一些额外的样板,但它的好处是如果您想对数据结构的不同部分使用不同的生成器,您可以有更多的控制权。

Here's an example where an Arbitrary list of longs is non-empty by default, but is empty for B .这是一个示例,其中 long 的Arbitrary列表默认为非空,但对于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
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM