Hi Eric,
On 12/23/2014 06:31 AM, etorreborre wrote:
> Thanks Rickard for your explanation.
>
> I still need to through this in my head. For example it is not clear to
> me why Arbitrary.arbitrary should return a Gen with all these methods.
> Wouldn't a Gen trait with just a `doApply` method be enough? Then the
> current Gen would be a GenData implementing Gen but having additional
> combinators to build GenData instances.
I'm not really following what you mean. The core methods of Gen is
really map and flatMap, to support the current monadic style when
constructing generators. I don't see how separating stuff into Gen and
GenData would work (or make things better).
My suggestion was simply that if you want to support several different
type classes similar to Arbitrary, it wouldn't work just using "implicit
val genInt: Gen[Int]". Of course, you could still rely on using scope
for picking the right implicit generator, but I don't see how that would
be better than having different type classes.
> > I mean, if you have refined your integer to SmallInt it seems strange
> to then talk about
> > Arbitrary[SmallInt], since (to me) "Arbitrary" means something
> un-refined.
>
> For me the Arbitrary[SmallInt] is still an un-refined value but for the
> type SmallInt.
>
> Also in practice we often create things like:
>
> case class Line(fields: List[String]) {
> def line = fields.mkString("|")
> }
>
> Then we get an Arbitrary[Line] (instead of a straight Arbitrary[String]
> representing a line), we can feed a (l: Line).line to a parser for
> example and check that we get all the original (line: Line).fields.
>
> But that's beside the point.
Yes, there's absolutely nothing wrong with your approach. As I said, I
think it depends entirely on personal taste whether you define a
"newtype" or use a specific generator.
> More to the point, I am going to propose in specs2 (in 3.0) some
> additional sugar on top of ScalaCheck to be able to:
>
> - set specific parameters on a property
This will be in ScalaCheck 2.0 or before.
> - set specific Pretty values for each parameter on a property
This might be useful, but I'm not sure. I'd be happy to see use cases
where the same type should be presented in different ways for different
properties.
> - set specific Arbitrary/Shrink/Gen instance on a property
I'm not sure about this. Arbitrary is tied to Prop.forAll or explicit
use of Arbitrary.arbitrary, and maybe that should be emphasized by
something like forAllArbitrary.
Shrink will be more tied to Gen in ScalaCheck 2.0. Basically a generator
that is responsible for constructing a value should also be responsible
for deconstructing it (by shrinking it). This should help with the more
unexpected shrinking effects you currently can see in ScalaCheck, since
currently Shrink knows nothing about how a value has been produced.
So other than picking a specific generator (by using something like
"forAll(gen) { x => ... }") I don't think there needs to be a way to
bring in different Arbitrary instances for the same types. My feeling is
that Arbitrary should have the specific meaning I tried to describe
earlier, and then there ideally should be just one Arbitrary instance
per type. I don't know if we can enforce this in some way other than
convention though. And I'm keen on hearing other peoples opinion on that
idea.
> - have a way to declare which of the arguments should be collected
> (opposed to any value at the moment)
I'm not sure what you mean here. But I fully agree that there can be
much better support for collecting data samples and statistics during a
test run.
> - declare the verbosity of the property
This should probably be handled like the rest of the params.
> - pass parameters from the command line to override the property
> parameters (that one is really nice when testing)
Yeah, the whole parameter thing should be cleaned up and improved, so
you can set parameters (ideally down to individual properties) on all
levels (command line, sbt, Properties, Prop), with sensible override
semantics.
> - output the args for a failed property so that strings are quoted (if
> the arg is a case class) in order to be able to more easily copy and
> paste from the console and recreate a failed example
In ScalaCheck 2.0, generators should be deterministic, and there should
be some support to output the seed that was used for a failed test, and
that seed should be everything you need to exactly reproduce the test
(within ScalaCheck). But maybe you are after something more like: I want
to create a traditional unit test out of this property failure. That's
an interesting idea, and I wonder if it could be built into Pretty and
controlled by some flag (like verbosity).
> If you implement #120
> <
https://github.com/rickynils/scalacheck/issues/120>, some of this might