QuickCheck-2.8: Automatic testing of Haskell programs

Safe HaskellNone
LanguageHaskell98

Test.QuickCheck.Monadic

Contents

Description

Allows testing of monadic values. Will generally follow this form:

prop_monadic a b = monadicIO $ do
  a' <- run (f a)
  b' <- run (f b)
  -- ...
  assert someBoolean

Example using the FACTOR(1) command-line utility:

import System.Process
import Test.QuickCheck
import Test.QuickCheck.Monadic

-- $ factor 16
-- 16: 2 2 2 2
factor :: Integer -> IO [Integer]
factor n = parse `fmap` readProcess "factor" [show n] "" where

  parse :: String -> [Integer]
  parse = map read . tail . words

prop_factor :: Positive Integer -> Property
prop_factor (Positive n) = monadicIO $ do
  factors <- run (factor n)

  assert (product factors == n)
>>> quickCheck prop_factor
+++ OK, passed 100 tests.

See the paper "Testing Monadic Code with QuickCheck".

Synopsis

Property monad

newtype PropertyM m a Source

The property monad is really a monad transformer that can contain monadic computations in the monad m it is parameterized by:

  • m - the m-computations that may be performed within PropertyM

Elements of PropertyM m a may mix property operations and m-computations.

Constructors

MkPropertyM 

Fields

unPropertyM :: (a -> Gen (m Property)) -> Gen (m Property)
 

Monadic specification combinators

run :: Monad m => m a -> PropertyM m a Source

The lifting operation of the property monad. Allows embedding monadic/IO-actions in properties:

log :: Int -> IO ()

prop_foo n = monadicIO $ do
  run (log n)
  -- ...

assert :: Monad m => Bool -> PropertyM m () Source

Allows embedding non-monadic properties into monadic ones.

pre :: Monad m => Bool -> PropertyM m () Source

Tests preconditions. Unlike assert this does not cause the property to fail, rather it discards them just like using the implication combinator ==>.

This allows representing the Hoare triple

{p} x ← e{q}

as

pre p
x <- run e
assert q

wp :: Monad m => m a -> (a -> PropertyM m b) -> PropertyM m b Source

The weakest precondition

wp(x ← e, p)

can be expressed as in code as wp e (\x -> p).

pick :: (Monad m, Show a) => Gen a -> PropertyM m a Source

Quantification in a monadic property, fits better with do-notation than forAllM.

forAllM :: (Monad m, Show a) => Gen a -> (a -> PropertyM m b) -> PropertyM m b Source

An alternative to quantification a monadic properties to pick, with a notation similar to forAll.

monitor :: Monad m => (Property -> Property) -> PropertyM m () Source

Allows making observations about the test data:

monitor (collect e)

collects the distribution of value of e.

monitor (counterexample "Failure!")

Adds "Failure!" to the counterexamples.

stop :: (Testable prop, Monad m) => prop -> PropertyM m a Source

Run functions

monadicIO :: PropertyM IO a -> Property Source

Runs the property monad for IO-computations.

prop_cat msg = monadicIO $ do
  (exitCode, stdout, _) <- run (readProcessWithExitCode "cat" [] msg)

  pre (ExitSuccess == exitCode)

  assert (stdout == msg)
>>> quickCheck prop_cat
+++ OK, passed 100 tests.

monadicST :: (forall s. PropertyM (ST s) a) -> Property Source

Runs the property monad for ST-computations.

-- Your mutable sorting algorithm here
sortST :: Ord a => [a] -> ST s (MVector s a)
sortST = thaw . fromList . sort

prop_sortST xs = monadicST $ do
  sorted  <- run (freeze =<< sortST xs)
  assert (toList sorted == sort xs)
>>> quickCheck prop_sortST
+++ OK, passed 100 tests.

runSTGen :: (forall s. Gen (ST s a)) -> Gen a Source