Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing IO Int and similar in Haskell

Tags:

haskell

From Ninety-Nine Haskell Problems:

Question 23: Extract a given number of randomly selected elements from a list.

This is a partial solution. For simplicity, this code just selects one element from a list.

import System.Random (randomRIO)

randItem :: [a] -> IO a
randItem xs = do
    i <- randomRIO (0,length xs - 1)
    return $ xs !! i

so randItem [1..10] would return an IO Int that corresponds to (but does not equal) some Int from 1 through 10.

So far, so good. But what kind of tests can I write for my randItem function? What relationship--if any--can I confirm between the input and output?

I can use the same logic as the above function to produce m Bool, but I cannot figure out how to test for m Bool. Thank you.

like image 536
Shay Avatar asked Oct 17 '17 13:10

Shay


1 Answers

There's a couple of things you can do. If you're using QuickCheck, you could write the following properties:

  • The length of the returned list should be equal to the input length.
  • All elements in the returned list should be elements of the list of candidates.

Apart from that, the beauty of Haskell's Random library is that (as most other Haskell code) it's deterministic. If, instead of basing your implementation on randomRIO, you could base it on randomR or randomRs. This would enable you to pass some known RandomGen values to some deterministic unit test cases (not QuickCheck). These could serve as regression tests.


I've now published an article about the above approach, complete with source code.

like image 189
Mark Seemann Avatar answered Nov 06 '22 12:11

Mark Seemann