Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does QuickCheck give up?

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?

like image 716
sdasdadas Avatar asked Aug 29 '13 05:08

sdasdadas


People also ask

How does QuickCheck work Haskell?

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.

How do I use QuickCheck?

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 .


1 Answers

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)
like image 110
Satvik Avatar answered Nov 16 '22 00:11

Satvik