문제

Say I want to write some unit tests for the (!!) function.

my_prop xs n = ...

I want to restrict n to only valid indexes and I know I could do something like

my_prop xs n = (not.null) (drop n xs) ==> ...

But this makes it so that the vast majority of the generated cases are invalid and get thrown away. Is there a way I can set things up so that QuickCheck generates the xs list first and uses its value to generate only valid cases of n?

도움이 되었습니까?

해결책

Using forAll, you can specify a generator for n which depends on the earlier arguments, e.g.

my_prop (NonEmpty xs) = forAll (choose (0, length xs - 1)) $ \n -> ...

다른 팁

You can make a generator that only creates valid indices and write your property like

import Test.QuickCheck
import Test.QuickCheck.Gen
import System.Random

indices :: [a] -> Gen Int
indices xs = MkGen $ \sg _ -> fst $ randomR (0, length xs - 1) sg

my_prop :: [Char] -> Property
my_prop xs = not (null xs) ==> forAll (indices xs) (\i -> xs !! i /= '0')

eliminating the Int argument.

As suggested by Daniel Wagner, one possibility is creating my own datatype and giving it an Arbitrary instance.

data ListAndIndex a = ListAndIndex [a] Int deriving (Show)

instance Arbitrary a => Arbitrary (ListAndIndex a) where
   arbitrary = do
     (NonEmpty xs) <- arbitrary
     n  <- elements [0..(length xs - 1)]
     return $ ListAndIndex xs n

NonEmpty is from a custom type in Test.QuickCheck.Modifiers for generating non empty lists.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top