I thought it was time to try FsCheck, but it turned out to be tougher than I thought. There is a lot of documentation on Arb , generators, etc., but there seems to be no indication on how to apply this knowledge. Or I just don't get it.
What can complicate this is that the connection between tests, properties, generators, arbitrariness, compression, and, in my case, randomness (some tests automatically generate random data, others not) is not clear to me. I don't have a Haskell background, so that doesn't help either.
Now for the question: how can I generate random integers?
My test case can be explained using the multiplication properties of, say, distributivity:
static member ``Multiplication is distributive`` (x: int64) yz = let res1 = x * (y + z) let res2 = x * y + x * z res1 = res2
When I run this using Check.Verbose or NUnit integration, I get test sequences, for example:
0: (-1L, -1L, -1L) 1: (-1L, -1L, 0L) 2: (-1L, -1L, -1L) 3: (-1L, -1L, -1L) 4: (-1L, 0L, -1L) 5: (1L, 0L, 2L) 6: (-2L, 0L, -1L) 7: (-2L, -1L, -1L) 8: (1L, 1L, -2L) 9: (-2L, 2L, -2L)
After 1000 tests, he did not receive more than 100L . Somehow, I suggested that this “automatically” selects random numbers evenly distributed throughout the int64 range, at least the way I interpreted the documentation.
Since this is not the case, I started experimenting and came up with stupid solutions like the following in order to get higher numbers:
type Generators = static member arbMyRecord = Arb.generate<int64> |> Gen.where ((<) 1000L) |> Gen.three |> Arb.fromGen
But this is becoming incredibly slow and clearly not suitable. I am sure there should be a simple solution that I am missing. I tried with Gen.choose(Int64.MinValue, Int64.MaxValue) , but this only supports ints, not longs (but even with just ints I could not get it to work).
In the end, I need a solution that works for all primitive numeric data types, including their maxes and mins, their zeros and ones, and some random selection from what's inside.