FsCheck icon indicating copy to clipboard operation
FsCheck copied to clipboard

Allow tuning of size distribution introduced in 2.10.0

Open glchapman opened this issue 6 years ago • 5 comments

From my experience with other QuickCheck libraries, I was surprised by the prevalence of ("", 0) in this:

> Gen.sample 10 10 Arb.from<(string * int) list>.Generator;;
val it : (string * int) list list =
  [[("", 0); ("", 4)];
   [(null, 0); ("", 0); ("", 0); ("", 0); ("", 0); ("", 0); ("", 0); ("", 0);
    ("", 0); ("", 0)]; [("lb", 1)];
   [("", 0); ("", 0); (null, 0); ("", 0); ("", 4); ("", 0)];
   [("", 0); ("3", 1); ("", 0); (null, 0); ("", 0); ("", 0); ("", 0); ("", 0);
    ("", 0)]; [("", -1); ("", 0); ("", 0); ("", 0)]; [("", 0); ("", -1)];
   [(null, 0); ("", 0); ("", 0); ("", 0); ("", 0); ("", 0)];
   [("", 0); (null, 0); ("^", -1)]; [("QAz", 0)]]

I've briefly scanned the paper you reference in the release notes for 2.10.0, and, if I understand correctly, FSCheck is only using the fixedSize Distributor described in the paper. I think it would be useful to implement the other Distributors described, and provide some mechanism for selecting them when generating data.

glchapman avatar Jul 14 '18 15:07 glchapman

I became convinced that the way the original quickcheck distributed size is less than ideal; what we're used to is not necessarily better.

Also, my sense is that adding distributors causes more complexity than it's worth.

The options available in FsCheck today, and likely for the forseeable future, are:

  • for coarse control, simply increase the size;
  • for fine-grained control over how size is distributed, write a custom generator using the size related functions on Gen.

kurtschelfthout avatar Jul 18 '18 10:07 kurtschelfthout

Just to let you know I've changed my mind about what I said above. I now think we should somehow allow either the old or the new behavior for product-like types, and that it should be configurable. I need to think a bit of how to fit it into the API though, and it will go into v3.

kurtschelfthout avatar Jan 16 '21 21:01 kurtschelfthout

I am having similar issue, i.e.: having such a signature: rates: Map<ProviderId, RateObject list> and MaxTest=5 the FsCheck is generating, almost always, for 3 of 5 times the map with empty list.

On the other hand, if I change rates to: rates: RateObject list and MaxTest=5 then FsCheck is generating 5 times a very long lists. Not even once the list is empty.

The RateObject looks like this:

type ProviderId = ProviderId of string
type Currency = Currency of string
type Pair = Currency * Currency
type Rate = Rate of decimal
type RateObject = { Pair: Pair; Rate: Rate; ValidFrom: Instant }

What is wrong? Why the generated data is so bad? On one side the lists are empty 3/5 times, on the other I cannot even get an empty list to see if the code handles it well. Please advise.

witoldsz avatar Nov 29 '21 19:11 witoldsz

I am having this problem too.

When generating a record with a few string fields, in a reasonable (100-200) amount of tests the strings are not getting longer than 1, rarely 2 characters and are very often null.

This is problematic because this way the actual coverage is very small.

Has anyone found a workaround? Except to tuning startSize, which is not a greatest idea?

AlexeyRaga avatar Jul 12 '22 06:07 AlexeyRaga

Has anyone found a workaround? Except to tuning startSize, which is not a greatest idea?

Why not? Increasing StartSize and EndSize seems fine to me.

kurtschelfthout avatar Jul 12 '22 08:07 kurtschelfthout