Search code examples
c#fscheck

How to limit the input values in FsCheck?


I have a FsCheck-Property that is like this:

[Property]
public Property ConversionCanBeInversedForAllUnits(double input, string unit1, string unit2) 
{ ... }

FsCheck will feed it random values. I want to limit the input of the strings to members of some fixed set.

The obvious solution works:

[Property]
public Property ConversionCanBeInversedForAllUnits(double input, int unit1Int, int unit2Int) 
{
 string unit1 = units[unit1Int % units.Lenght];
 string unit2 = units[unit2Int % units.Lenght];
 input = math.clamp(min, input, max);
}

I don't think its indented to be used this way.

The second attempt didn't work. First I added some class

  public class MyTestDataCreator
  {
    private static string[] lengthUnits = new string[] { "m", "mm" };
    public static Arbitrary<string> lenghtunits()
    {
      // Does not compile.
      return FsCheck.Gen.Choose(0, lengthUnits.Length).Select(index => lengthUnits[index]);
    }

    public Gen<double> DoubleGen()
    {
      return FsCheck.Gen.Choose(0, 1000);
    }
}

And changed the Attribute to

[Property(Arbitrary = new Type[] { typeof(MyTestDataCreator) })]

That leaves me with the exception

Message: System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
---- System.Exception : No instances found on type Prop.MyTestDataCreator. Check that the type is public and has public static members with the right signature.

Which begs the question: What is the right signature?


Solution

  • lengthunits() has the right signature: returning an Arbitrary instance and a method without paramters.

    Try turning a Gen<T> into an Arbitrary<T> by calling ToArbitrary() on it.

    Arbitrary will become useful if you want to write shrinkers. Arbitrary = generator + shrinker.