QuickCheck: testing every item in the final set
I'm looking for a way to test a function on a deterministic set of values ββalways (not a randomly selected value from a list). For example, I would like to check that
f :: (Num a) => a -> Bool
f x = (x - 2) == (x-3+1)
runs for exactly Int
1, 3 and 5, without explicit writing
testGroup "f tests" $ map (testProperty . property) [f (1::Int), f (3::Int), f (5::Int)]
Instead, I want to have some type of wrapper around Int
so that when f
this type is called , it tests f
with values ββ1,3 and 5 each time.
The motivation for this is this answer for testing polymorphic functions.
I came up with a solution using my own instance for Arbitrary [Some c]
:
data Some c where
Some :: (Show a, Arbitrary a, c a) => a -> Some c
instance Arbitrary [Dict c] => Arbitrary [Some c] where
arbitrary = do
dicts :: [Dict c] <- arbitrary
sequence $ map (\(Dict (Proxy::Proxy a)) -> liftM Some (arbitrary :: Gen a)) dicts
data Dict c where
Dict :: (Show a, Arbitrary a, c a)
=> Proxy a -> Dict c
class ClassToTest a
-- where ...
instance Arbitrary [Dict ClassToTest] where
arbitrary = return $ [Dict (Proxy::Proxy TYPE1),
Dict (Proxy::Proxy TYPE2)]
testAll :: forall a . (Arbitrary [a]) => (a -> Bool) -> Gen Bool
testAll f = do
xs' <- arbitrary :: Gen [a]
return $ and $ map f xs'
Then I could write a function
myTest :: (ClassToTest a) => a -> Bool
myTest x = error ""
theTest :: Test
theTest = testProperty "mytest" $ testAll myTest
which generates a random value TYPE1
and runs myTest
, then generates a random value for TYPE2
and runs again myTest
. The idea is that the TYPE * list is very large, so I would rather not rely on random selection to check that everything in the list is checked. The problem with my approach is that QuickCheck already has a shared instance for (Arbitrary a) => Arbitrary [a]
, so this code requires -XOverlappingInstances
. Is there a better way?
source to share
No one has answered this question yet
See similar questions:
or similar: