I have been on a journey to learn F# via implementing the Game of Life. Thus, I have decided to dig into Property-based Testing.
Property-based testing is another technique used within test automation. Unlike unit tests, which test specific examples on a case-by-case basis, property-based tests target the properties or principles of the function itself. Thus, I now view unit tests (aka: example-based tests) as a design tool for building systems. Furthermore, I view property-based tests as regression tests for each property of a function.
In the Game of Life, I wrote a function called getNeighbors:
let getNeighbors (coordinate:int*int) = let x,y = coordinate let west = x-1, y let northWest = x-1, y+1 let north = x, y+1 let northEast = x+1, y+1 let east = x+1, y let southEast = x+1, y-1 let south = x, y-1 let southWest = x-1, y-1 [west; northWest; north; northEast; east; southEast; south; southWest]
In the above code, a client passes in a coordinate in which the function will return a list of neighbors for that particular coordinate.
One property that I identified for the getNeighbors function is that a coordinate can have no more than eight neighbors.
To test this, I wrote the following property-based test:
[<Fact>] let ``cell can't have more than eight neighbors`` () = Check.QuickThrowOnFailure <| fun xy -> xy |> getNeighbors |> List.length < 9
QuickThrowOnFailure will throw an exception if any argument used within the expression triggers a false result.
The “<|" operator forwards the result of an expression on the right-hand side to a function on the left-hand side.
The test, by default, will pass in a range of values to this function. By default, the range consists of 100 values. However, the range is configurable with a little extra code.
The Nuget dependencies required to setup this test were XUnit, xunit.runner.visualstudio, and FsCheck.
There's also another function that's a good candidate for a property-based test. That function is the createGrid function. The createGrid function takes a rowCount as an argument.
I first attempted to write the test as the following:
let “number of cells in grid equals rowcount squared“ () =
fun rowCount -> rowCount >= 0 ==>
fun rowCount -> rowCount |> createGrid
|> List.length = rowCount * rowCount
However, the test failed as a result of using -1 as an argument for the number of rows. I'm still not sure how -1 got included as an argument though. Hence, I provided the precondition for the row count to be greater than zero. Unfortunately, I need help in identifying my misunderstanding. Thus, I hope to share the correct implementation for this property-based test in my next post.
In conclusion, I have been on a journey to learn F# via implementing the Game of Life. Thus, I have decided to dig into Property-based Testing.