Search code examples
haskellquickcheck

Quickcheck on custom datatype


I succesfully run a quickcheck on this:

testaroo = quickCheck $ checkWin

checkWin :: [(Int, ThePlayers)] -> Bool
checkWin [(1,_),(2,_),(3,_)] = True
checkWin [(4,_),(5,_),(6,_)] = True
checkWin [(7,_),(8,_),(9,_)] = True
checkWin [(1,_),(5,_),(9,_)] = True
checkWin [(3,_),(5,_),(7,_)] = True
checkWin [(1,_),(4,_),(7,_)] = True
checkWin [(2,_),(5,_),(8,_)] = True
checkWin [(3,_),(6,_),(9,_)] = True
checkWin _ = False

but when i try to run

testaroo = quickCheck $ removeFromList

removeFromList :: (Int, ThePlayers) -> [(Int, ThePlayers)] -> [(Int, ThePlayers)]
removeFromList tuple list = delete tuple list

I run into the following:

No instance for (Arbitrary ThePlayers)
      arising from a use of `quickCheck'
    Possible fix:
      add an instance declaration for (Arbitrary ThePlayers)
    In the expression: quickCheck
    In the expression: quickCheck $ removeFromList
    In an equation for `testaroo':
        testaroo = quickCheck $ removeFromList
Failed, modules loaded: none.

What I did to run my quickCheck on checkWin successfully I added

instance Arbitrary BoardState
    where
    arbitrary  = arbitrary

But in all honesty I'm not quite sure what this does :). Is there anyway I can make the test run on my removeFromList function?


Solution

  • QuickCheck has to generate random cases to test against your property, by

    No instance for (Arbitrary ThePlayers)
    

    It basically said it doesn't know how to generate a random ThePlayers value for the tests and you should implement an instance Arbitrary ThePlayers.


    Also the type of quickCheck is

    quickCheck :: Testable prop => prop -> IO () 
    

    Even if the module can generate random arguments for you, the function removeFromList doesn't look like a Testable (a property), neither checkWin: A property of a function is about: what is supposed to be the right result of it? What should the results satisfy? What's the relationship between arguments and the results? The QuickCheck module won't and can't generate property from your functions, you have to specify it yourself.

    (BTW your first test on checkWin got compiled only because it have a return type Bool by chance, it isn't indicating any property of your program and will fail almost every time)

    For example one property of reverse function from Data.List is: the reverse function should not change the length of the list, so a check based on this fact shoud be:

    prop_length :: [Int] -> Bool
    prop_length as = length as == length (reverse as)
    

    and then you can build a test based on it:

    test_propLength = quickCheck prop_length
    

    You may try some tutorials for more information.