10

In my tests I am making quite an extensive usage of Specs2 + ScalaCheck and there are some patterns to factor out. I still haven't found out if my functions should use an Arbitrary[T] or a Gen[T], since they are very similar:

sealed abstract class Arbitrary[T] {
  val arbitrary: Gen[T]
}

Would a function signature looks like that:

maxSizedIntervalArbitrary[A,B](implicit ordering:Ordering[A], genStart:Arbitrary[A], genEnd:Arbitrary[B]):Arbitrary[TreeMap[A,B]]

or should I work at the Gen abstraction level?

Edmondo
  • 19,559
  • 13
  • 62
  • 115
  • 1
    Possible duplicate of [Why do you need Arbitraries in scalacheck?](http://stackoverflow.com/questions/31111106/why-do-you-need-arbitraries-in-scalacheck) – Bruno Bieth Mar 21 '17 at 07:43

1 Answers1

4

I'd say do both:

def maxSizedIntervalArbitrary[A,B](genStart:Gen[A], genEnd:Gen[B])(implicit ordering:Ordering[A]):Gen[TreeMap[A,B]]

implicit def maxSizedIntervalArbitrary[A,B](implicit ordering:Ordering[A], genStart:Arbitrary[A], genEnd:Arbitrary[B]):Arbitrary[TreeMap[A,B]] = 
  Arbitrary(maxSizedIntervalArbitrary(arbitrary[A], arbitrary[B]))

Arbitrary is used to supply implicit Gens, basically, so this allows to use both forAll variants with explicit Gen and with implicit Arbitrary. I don't think non-implicit Arbitrary is ever useful.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • Makes sense. What about Arbitrary conflicts ?(There are implicits arbitrary defined in Arbitrary companion objects which are making my life impossible) – Edmondo Feb 24 '14 at 09:46
  • 1
    In this case I think you may have to avoid `Arbitrary` and use only `Gen` version. To minimize explicit passing of `Gen`s, you can add an overload taking `implicit Arbitrary` and still returning `Gen` as well. – Alexey Romanov Feb 24 '14 at 09:59