Just started looking at FsCheck, wrote several tests, and now I am wondering what is a good strategy for composing more complex arbitraries. Is registering arbitraries within arbitrary good approach? Something like this
public class DiscountAmountArbitrator
{
public static Arbitrary<DiscountAmount> DiscountAmounts()
{
Arb.Register<AmountArbitrary>();
var toReturn = (from a in Arb.Generate<Amount>()
select new DiscountAmount(a))
.ToArbitrary();
return toReturn;
}
}
public class AmountArbitrary
{
public static Arbitrary<Amount> Amounts()
{
return Arb.Generate<decimal>().Where(x => x > 0)
.Select(x => new Amount(x))
.ToArbitrary();
}
}
My advice would be, if you have different related arbitrary instances, add them to the same class and call the methods directly instead when there are dependencies between the different instances. Then when using any of the Arbitrary instances in tests, register them all at once.
This makes your code less dependent on the order in which things are executed (Arb.Register is a fundamentally side-effecting operation, and this can lead to some unexpected results). There is no real advantage to putting Arbitrary methods on different classes. So I would rewrite what you have as follows:
public class Arbitraries
{
public static Arbitrary<DiscountAmount> DiscountAmounts()
{
var toReturn = (from a in Amounts().Generator
select new DiscountAmount(a))
.ToArbitrary();
return toReturn;
}
public static Arbitrary<Amount> Amounts()
{
return Arb.Generate<decimal>().Where(x => x > 0)
.Select(x => new Amount(x))
.ToArbitrary();
}
}