3

Is it possible to generate data, specifically a list, with fscheck for use outside of fscheck? I'm unable to debug a situation in fscheck testing where it looks like the comparison results are equal, but fscheck says they are not.

I have this generator for a list of objects. How do I generate a list I can use from this generator?

let genListObj min max  = Gen.listOf Arb.generate<obj> |> Gen.suchThat (fun l -> (l.Length >= min) && (l.Length <= max))
Jack Fox
  • 953
  • 6
  • 20
  • Use `Gen.eval`, see http://fscheck.codeplex.com/SourceControl/changeset/view/fd9da99ee77d#FsCheck.Test%2fHelpers.fs . However FsCheck outputs the generated data for the failing case, so this shouldn't generally be necessary. – Mauricio Scheffer Oct 15 '12 at 19:47
  • I thought I tried Gen.eval. I'll take another look. Not obvious to me where fsCheck is outputting this data in a property test. Committing some interesting stuff to my public branch and a long message to issue #98 right now. – Jack Fox Oct 15 '12 at 21:43
  • 1
    By the way, avoid Gen.suchThat. It basically generates random values until some pass the filter, so it can take a long time. For you example, would be better to generate a random length first (using e.g. Gen.choose) then generate a list of that length (using Gen.listOfLength). – Kurt Schelfthout Oct 16 '12 at 16:00
  • Thanks for the tip on Gen.listOfLength. I don't know how I overlooked that. – Jack Fox Oct 19 '12 at 03:44
  • Gen.eval expects Random.StdGen. I want to generate data from a Gen I constructed (which works within FsCheck by means of Arb.fromGen) and have access to the actual data for further processing. – Jack Fox Oct 19 '12 at 04:03
  • 1
    FsCheck is not set up by default to do that, but it's reasonably easy to write a function. I think I could help you better if you post the actual property you're are having problems with - in particular I don't understand "fscheck says they are not" - fscheck does not have any special ideas on equality. – Kurt Schelfthout Oct 19 '12 at 11:54

1 Answers1

7

Edit: this function is now part of the FsCheck API (Gen.sample) so you don't need the below anymore...

Here is a sample function to generate n samples from a given generator:

let sample n gn  = 
   let rec sample i seed samples =
       if i = 0 then samples
       else sample (i-1) (Random.stdSplit seed |> snd) (Gen.eval 1000 seed gn :: samples)
   sample n (Random.newSeed()) []

Edit: the 1000 magic number in there represents the size of the generated values. 1000 is pretty big - e.g. sequences will be between 0 and 1000 elements long, and so will strings, for example. If generation takes a long time, you may want to tweak that value (or take it in as a parameter of the function).

Kurt Schelfthout
  • 8,880
  • 1
  • 30
  • 48
  • Wow! So far works flawlessly, even on a gen that returns a tuple of my custom data structure and a list. Many thanks. – Jack Fox Oct 19 '12 at 17:10