I am using QuickCheck
to test the following program:
{-# LANGUAGE TemplateHaskell #-}
import Test.QuickCheck
import Test.QuickCheck.All
elementAt :: (Integral b) => [a] -> b -> a
elementAt [x] _ = x
elementAt (x:xs) 1 = x
elementAt (x:xs) b = elementAt xs (b - 1)
prop_elementAt xs b = length xs > 0 && b >= 0 && b < length xs ==> elementAt xs (b + 1) == xs !! b
main = $(quickCheckAll)
Although the response varies, I constantly receive the message
*** Gave up! Passed only x tests.
Is this something I should be concerned about? Or does the nature of the test input dictate how long QuickCheck will run for?
QuickCheck is a tool for testing Haskell programs automatically. The programmer provides a specification of the program, in the form of properties which functions should satisfy, and QuickCheck then tests that the properties hold in a large number of randomly generated cases.
QuickCheck uses types to generate test data, starting with short lists and small integers and generating progressively larger values. If the property fails for some value, a counter-example is shown; otherwise the test succeeds. Run the code bellow to test our distributivity law for reverse .
The way ==>
works is first quickcheck will generate random values for xs
and b
, then check if the predicate length xs > 0 && b >= 0 && b < length xs
is satisfied only then it will check for the satisfiability of the property.
As there is a limit for how many test cases it will generate it might happen that lots of the time the above predicate is not satisfied. So quickcheck gives up before generating enough valid testcases (satisfying the predicate).
You should instead declare Arbitrary
instance to a newtype to generate only testcases satisfying those predicates.
{-# LANGUAGE TemplateHaskell #-}
import Test.QuickCheck
import Test.QuickCheck.All
elementAt :: (Integral b) => [a] -> b -> a
elementAt [x] _ = x
elementAt (x:xs) 1 = x
elementAt (x:xs) b = elementAt xs (b - 1)
prop_elementAt (Foo xs b) = elementAt xs (b + 1) == xs !! b
data Foo a b = Foo [a] b deriving (Show)
instance (Integral b, Arbitrary a, Arbitrary b) => Arbitrary (Foo a b) where
arbitrary = do
as <- listOf1 arbitrary -- length xs > 0
b <- choose (0,length as - 1) -- b >= 0 and b < length xs
return (Foo as $ fromIntegral b)
main = $(quickCheckAll)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With