Skip to content

Instantly share code, notes, and snippets.

@StephenStrickland
Last active July 4, 2023 13:00
Show Gist options
  • Save StephenStrickland/c52e2337bba79d211bc0ca165dbeffde to your computer and use it in GitHub Desktop.
Save StephenStrickland/c52e2337bba79d211bc0ca165dbeffde to your computer and use it in GitHub Desktop.
FsCheck in C# Cheat Sheet

FsCheck C# Cheat Sheet

What is FsCheck?

GitHub: FsCheck

Learning Resources

  1. https://medium.com/criteo-engineering/introduction-to-property-based-testing-f5236229d237
  2. https://increment.com/testing/in-praise-of-property-based-testing/
  3. https://techbeacon.com/app-dev-testing/how-make-your-code-bulletproof-property-testing
  4. https://www.infoq.com/interviews/blasucci-fsharp-fscheck/
  5. Great talk from Scott Wlaschin - https://www.youtube.com/watch?v=99oO-6EIyck

Cheat Sheet

Install FsCheck

See FsCheck README Instructions: https://github.com/fscheck/FsCheck#releases

Generate Single Primitive Value

// 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

Generate List of Primitives

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

Generate Random Instance of Class

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
}

Generate List of Random Instances of Class

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
   }
]

Generate Specific Class Data

// 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
   }
]

Pair FsCheck with Bogus

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment