Community
Modules 18

Test.QuickCheck.Monadic

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\` 'System.Process.readProcess' \"factor\" [show n] \"\" where

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

prop_factor :: Positive Integer -> Property
prop_factor ('Test.QuickCheck.Modifiers.Positive' n) = 'monadicIO' $ do
  factors \<- 'run' (factor n)

  'assert' (product factors == n)

See the paper "Testing Monadic Code with QuickCheck".

Property monad

newtype PropertyM m a

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.

MkPropertyM :: (a -> Gen (m Property)) -> Gen (m Property) -> PropertyM m a

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

Monadic specification combinators

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

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 ()

Allows embedding non-monadic properties into monadic ones.

assertWith :: Monad m => Bool -> String -> PropertyM m ()

Like assert but allows caller to specify an explicit message to show on failure.

Example:

do
  assertWith True  "My first predicate."
  assertWith False "My other predicate."
  ...
Assertion failed (after 2 tests):
    Passed: My first predicate
    Failed: My other predicate

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

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

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

Quantification in a monadic property, fits better with do-notation than forAllM. Note: values generated by pick do not shrink.

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

Quantification in monadic properties to pick, with a notation similar to forAll. Note: values generated by forAllM do not shrink.

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

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

Run functions

monadic :: (Testable a, Monad m) => (m Property -> Property) -> PropertyM m a -> Property

monadic' :: (Testable a, Monad m) => PropertyM m a -> Gen (m Property)

monadicIO :: Testable a => PropertyM IO a -> Property

Runs the property monad for IO-computations.

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

  pre ('System.Exit.ExitSuccess' == exitCode)

  assert (stdout == msg)

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

Runs the property monad for ST-computations.

-- Your mutable sorting algorithm here
sortST :: Ord a => [a] -> 'Control.Monad.ST.ST' s (MVector s a)
sortST = 'Data.Vector.thaw' . 'Data.Vector.fromList' . 'Data.List.sort'

prop_sortST xs = monadicST $ do
  sorted  \<- run ('Data.Vector.freeze' =<< sortST xs)
  assert ('Data.Vector.toList' sorted == sort xs)

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

Exceptions

assertException :: E.Exception exc => (exc -> Bool) -> a -> Property

Evaluate the value to Weak Head Normal Form (WHNF) and fail if it does not result in an expected exception being thrown.

(exc -> Bool)

Return `True` if that is the exception that was expected

a

Value that should result in an exception, when evaluated to WHNF

assertExceptionIO :: E.Exception exc => (exc -> Bool) -> IO a -> Property

Make sure that a specific exception is thrown during an IO action. The result is evaluated to WHNF.

An action that should throw the expected exception

(exc -> Bool)

Return `True` if that is the exception that was expected

assertDeepException :: (NFData a, E.Exception exc) => (exc -> Bool) -> a -> Property

Same as `assertException`, but evaluate the value to Normal Form (NF) and fail if it does not result in an expected exception being thrown.

(exc -> Bool)

Return True if that is the exception that was expected

a

Value that should result in an exception, when fully evaluated to NF

assertDeepExceptionIO :: (NFData a, E.Exception exc) => (exc -> Bool) -> IO a -> Property

Make sure that a specific exception is thrown during an IO action. The result is evaluated to NF.

An action that should throw the expected exception

(exc -> Bool)

Return True if that is the exception that was expected

Instances

6
  • instance Functor (PropertyM m)
  • instance Applicative (PropertyM m)
  • instance Monad m => Monad (PropertyM m)
  • instance Monad m => Fail.MonadFail (PropertyM m)
  • instance MonadTrans PropertyM
  • instance MonadIO m => MonadIO (PropertyM m)
Build record and source files

Community contribution. The service has not verified this documentation. The generator reported 30 diagnostics.

Target: Linux on x86-64. Some inferred types and resolved links are not available.

Generator: aihc-haddock-aa6debbd-web-3

Metadata snapshot: f17ab6aeb2a7b6daf9fba7614097e138beeef85fa92c3fb7fdfed9ed0e49728c

Open the dependency plan · Download the documentation model

Import a package

Enter a package name and an exact version from Hackage. The site contains imported versions only.