Haskell QuickCheck best practices (especially when testing type classes)

haskell, testing

Solution

I believe the `prop_` convention came from QC coming with a script that ran all functions that started with `prop_` as tests. So there's no real reason to do so, but it does visually stand out (so the property for a function `foo` is `prop_foo`).

And there's nothing wrong with testing internals. There are two ways of doing so:

Put the properties in the same module as the internals. This makes the module bigger, and requires an unconditional dependency on QC for the project (unless you use CPP hackery).

Have internals in a non-exported module, with the functions to actually be exported re-exported from another module. Then you can import the internal module into one that defines the QC properties, and that module is only built (and has a QC dependency) if a flag specified in the .cabal file is used.

If your project is large, then having separate `src/` and `test/` directories may be useful (though having a distinction may prevent you from testing internals). But if your project isn't all that big (and resides under one overall module hierarchy anyway), then there's no real need to split it up like that.

As Norman Ramsey said in his answer, for type classes you can just define the property as being on the typeclass and use accordingly.

Problem

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?

Original source