How to use FsCheck to generate random numbers as input for property-based testing
<p>I thought it's time to try out FsCheck but it proves tougher than I thought. There's a lot of documentation on <code>Arb</code>, generators and so on, but there doesn't seem to be any guidance in how to apply that knowledge. Or I'm just not getting it.</p>

<p>What may make it harder to grasp is that the relation between tests, properties, generators, arbitraries, shrinking and, in my case, randomness (some tests automatically generate random data, others don't) is not clear to me. I don't have a Haskell background so that doesn't help much either.</p>

<p>Now for the question: how do I generate random integers?</p>

<p>My test scenario can be explained on the properties of multiplication, let's say distributivity:</p>

<pre><code>static member  ``Multiplication is distributive`` (x: int64) y z =
    let res1 = x * (y + z)
    let res2 = x * y + x * z

    res1 = res2

// run it:
[&lt;Test&gt;]
static member FsCheckAsUnitTest() =
    Check.One({ Config.VerboseThrowOnFailure with MaxTest = 1000 }, ``Multiplication is distributive``)
</code></pre>

<p>When I run this with <code>Check.Verbose</code> or the NUnit integration, I get test sequences like:</p>

<pre><code>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)
</code></pre>

<p>After 1000 tests it hasn't gotten over <code>100L</code>. Somehow I imagined this would "automatically" choose random numbers evenly distributed over the whole range of <code>int64</code>, at least that's how I interpreted the documentation. </p>

<p>Since it doesn't, I started experimenting and came up with silly solutions like the following to get higher numbers:</p>

<pre><code>type Generators = 
    static member arbMyRecord =
        Arb.generate&lt;int64&gt;
        |&gt; Gen.where ((&lt;) 1000L)
        |&gt; Gen.three
        |&gt; Arb.fromGen
</code></pre>

<p>But this becomes incredibly slow and is clearly not the right approach. I'm sure there must be a simple solution that I'm missing. I tried with <code>Gen.choose(Int64.MinValue, Int64.MaxValue)</code>, but this only supports ints, not longs (but even with just ints I couldn't get it working). </p>

<p>In the end I need a solution that works for all the primitive numeric data types, that includes their maxes and mins, their zeroes and ones, and some random selection from whatever is within.</p>