Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell QuickCheck best practices (especially when testing type classes)

Tags:

I've just started using QuickCheck with a bunch of Haskell code. I'm behind the times, I know. This question is a two-parter:

Firstly, what are the general best-practices for Quick Check? So far, I've picked up the following:

  • Name your tests prop_* (annoying, because everything else is camelCase)
  • Test exported code (if you're testing internals you're likely doing it wrong)
  • Test properties, not examples
    • Don't say X is out of range, Y is in range
    • Instead, say if x is out of range, normalize x ≠ x (or some other such property)

But I'm still grasping at other best practices. Particularly:

  • Where are properties kept?
    • The same file?
    • in a test/ directory? (If so, then how do you import the stuff in src/?)
    • in a Properties/ directory under src?

Most importantly, how do we tend to go about testing properties on type classes? For example, consider the following (simplified) type class:

class Gen a where
    next :: a -> a
    prev :: a -> a

I'd like to test the property ∀ x: prev (next x) == x. Of course, this involves writing tests for each instance. It's tedious to write the same property for each instance, especially when the test is more complicated. What's the standard way to generalize such tests?

like image 935
So8res Avatar asked Apr 06 '12 00:04

So8res


1 Answers

It's tedious to write the same property for each instance

You don't do this. You write the property once for the class:

class Gen a where
    next :: a -> a
    prev :: a -> a

np_prop :: (Eq a, Gen a) => a -> Bool
np_prop a = prev (next a) == a

Then to test it, you cast to a particular type:

quickCheck (np_prop :: Int -> Bool)
quickCheck (np_prop :: String -> Bool)

Your other questions I can't help with.

like image 187
Norman Ramsey Avatar answered Oct 04 '22 13:10

Norman Ramsey