GitHub: FsCheck
Learning Resources
- https://medium.com/criteo-engineering/introduction-to-property-based-testing-f5236229d237
- https://increment.com/testing/in-praise-of-property-based-testing/
- https://techbeacon.com/app-dev-testing/how-make-your-code-bulletproof-property-testing
- https://www.infoq.com/interviews/blasucci-fsharp-fscheck/
- Great talk from Scott Wlaschin - https://www.youtube.com/watch?v=99oO-6EIyck
See FsCheck README Instructions: https://github.com/fscheck/FsCheck#releases
// inclusive range to generate +- from 0
var range = 10;
// create a new random seed for the Generator. Can generate the same seed using Random.mkStdGen(<const seed val>) for deterministic values
var randomSeed = Random.newSeed();
var randomInt = Arb.Default.Int32().Generator.Eval(range, Random.newSeed());
// randomListOfInts
-5, -10, 2, -3, 9, 4, -5, -10, 2, -3, 9, 4, -5, -10, 2, -3, 9, 4, -6, -8
var range = 10; // inclusive range to generate +- from 0
var numberOfIntsToGenerate = 5;
var randomListOfInts = Arb.Default.Integer.Generator().Sample(range, numberOfIntsToGenerate)
// randomListOfInts
-5, -10, 2, -3, 9, 4, -5, -10, 2, -3, 9, 4, -5, -10, 2, -3, 9, 4, -6, -8
public class Person {
public Guid Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
var randomPerson = Arb.Generate<Person>().Eval(10, Random.newSeed());
// randomPerson
{
"Id":"84fe610d-6678-4e3d-097f-a166dca8ca8f",
"Name":"q",
"Age":0
}
Building off of the single instance example above
IList<Person> listOfRandomPersons = Gen.ListOf(Arb.Generate<Person>()).Eval(5, Random.newSeed()).ToList();
[
{
"Name":"",
"Id":"6ec99c52-a1bd-3f3a-4a5c-d2f46a85fb1d",
"Age":0
},
{
"Name":"",
"Id":"ea6810e8-ccae-d568-8146-68deaa6f9107",
"Age":0
},
{
"Name":"",
"Id":"872ae917-68b0-4fd2-970d-d9fbc0360224",
"Age":0
},
{
"Name":"",
"Id":"32971e5a-af90-33f8-6e90-06d297b92f51",
"Age":0
},
{
"Name":"",
"Id":"4d93f03c-8172-4ff0-72e1-5772e80a804c",
"Age":0
}
]
// randomly select number between 1 and 100
var ageGenerator = Gen.Choose(1, 100);
// use the default String Arbitrary
var nameGenerator = Arb.Default.StringWithoutNullChars().Generator;
// composes previous generators to randomly generate more specific data
var personGenerator =
from id in Arb.Default.Guid().Generator
from name in nameGenerator
from age in ageGenerator
select new Person {
Id = id,
Name = name.Get,
Age = age,
};
IList<Person> listOfRandomPersons = Gen.ListOf(personGenerator).Eval(5, Random.newSeed()).ToList();
//listOfRandomPersons
[
{
"Name":null,
"Id":"b0669a74-9fdf-87a4-c692-08cdef6572b9",
"Age":94
},
{
"Name":"",
"Id":"8dacf510-fad1-e147-0c2e-a470924233e3",
"Age":1
},
{
"Name":"\u0015",
"Id":"69a35002-556d-3be3-afd1-960c1960b33c",
"Age":36
},
{
"Name":"",
"Id":"4646a9a5-af10-96d5-4b17-39e9da8a137b",
"Age":43
}
]
Sometimes we want to generate data that more closely relates to our real world application data. We can use Bogus
to generate this "life-like" data and plug it into FsCheck.
Bogus GitHub