alwaysPositive :: Int -> Bool
alwaysPositive x = badImplementation x >= 0
alwaysPositiveCheck = property (alwaysPositive)
Frege and QuickCheck: Create properties
After going through the main parts of property base testing with QuickCheck and Frege now I’m focusing only in properties. Lets recall what was a property in the context of QuickCheck.
What is a property
A property is an executable specification meaning a function that holds for a set of values using the program (function or set of functions) you want to test.
Create a simple property
As a rule of thumb the easiest way of creating a property is to
create a function that returns a Bool. A function retuning a Bool
can be treated as a Testable
value. Then use the Testable
function
as argument of the property
function, to get a Property
value and
leave QuickCheck to do the rest. In summary:
-
Create a function that returns
Bool
-
Invoke
property
passing the previous function -
Invoke QuickCheck
Lets create a simple function. This function has certain properties:
-
Should double the absolute value of the number passed as argument if that number is greater than 0 and less or equals than 10
-
Otherwise returns 0
I’m using frege-gradle-plugin for these examples, actually I’m
executing ./gradlew fregeQuickCheck --t which executes and waits
until the source code changes to launch the tests again. Very useful
while developing.
|
This is the specification we have to respect:
Lets try a first version of our function:
badImplementation :: Int -> Int
badImplementation x = x * 2
And now execute QuickCheck to see if this first version holds:
c.BasicsCheck.alwaysPositiveBadCheck: *** Failed! (after 7 tests and 2 shrinks):
Falsifiable
-1
Error as expected. So just using a negative number as argument the function won’t hold. Ok, we should take the absolute number and then multiply by two.
goodImplementation :: Int -> Int
goodImplementation x
| x >= 0 && x <= limit = x * 2
| otherwise = 0
where limit = 10
alwaysPositive :: Int -> Bool
alwaysPositive x = goodImplementation x >= 0
alwaysPositiveCheck = property (alwaysPositive)
c.BasicsCheck.alwaysPositiveCheck: +++ OK, passed 100 tests
Perfect!! Ok this was a good warm up exercise, lets do something more complex.