Frage

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?

War es hilfreich?

Lösung

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 -> ...

Andere Tipps

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top