Larry LIU Xinyu
Larry LIU Xinyu

Reputation: 2073

How to generate test data with shuffle in QuickCeck

For a given list [1..n], where n is a random positive integer, I want to generate the test data with 2 steps:

  1. Shuffle the list, xs = shuffle [1..n];
  2. Random mutate a number x in xs to y, where 1 <= y <= n;

After these 2 steps, the new list is denoted as ys.

I wrote a program. It takes ys, and outputs (x, y), the function prototype is like this:

solve :: [a] -> (a, a)

I want to use Test.QuickCheck to test my program. How to generate such test data? I see there is a function in QuickCheck

shuffle :: [a] -> Gen [a]

But I have no idea about how to use it.

Upvotes: 1

Views: 236

Answers (1)

Paul Johnson
Paul Johnson

Reputation: 17786

The Gen monad in QuickCheck is basically a state monad with a random number generator as its state. So when you see

shuffle :: [a] -> Gen [a]

That means that this argument takes a list and returns a shuffled list "in" the Gen monad.

Because its a monad you can put it inside a do clause. Its not quite clear what you are asking for, but I think its something like this:

myTest :: Integer -> Gen [Integer]
myTest 0 = return []
myTest n = do
   ns <- shuffle [1..n]
   x <- choose (0,n-1)
   y <- choose (1,n)
   let (ns1,ns2) = splitAt x ns
   return $ ns1 ++ [y] ++ drop 1 ns2`

You can run an action in the Gen monad using generate, which returns a value in IO, or you can set up a new type for your test data and make it an instance of Arbitrary, which contains the function

arbitrary :: Gen a

Edit: Or as Zeta pointed out in the comments you can use forAll:

quickCheck $ forAll (myTest 10) $ \x -> ....

Upvotes: 2

Related Questions