hspec-wai-0.8.0: Experimental Hspec support for testing WAI applications

Safe Haskell | None
Language | Haskell2010

Test.Hspec.Wai.QuickCheck

Contents

- Re-exports
- Internals

Synopsis

- property :: Testable a => a -> Application -> Property
- (==>) :: Testable prop => Bool -> prop -> WaiProperty
- class Arbitrary a where
- module Test.QuickCheck.Gen
- class Testable a where
- data WaiProperty = WaiProperty {
  - unWaiProperty :: Application -> Property
  }

# Documentation

property :: Testable a => a -> Application -> Property Source #

(==>) :: Testable prop => Bool -> prop -> WaiProperty infixr 0 Source #

# Re-exports

class Arbitrary a where #

Random generation and shrinking of values.

Minimal complete definition

arbitrary

Methods

arbitrary :: Gen a #

A generator for values of the given type.

shrink :: a -> [a] #

Produces a (possibly) empty list of all the possible immediate shrinks of the given value. The default implementation returns the empty list, so will not try to shrink the value.

Most implementations of `shrink` should try at least three things:

1. Shrink a term to any of its immediate subterms.
2. Recursively apply `shrink` to all immediate subterms.
3. Type-specific shrinkings such as replacing a constructor by a simpler constructor.

For example, suppose we have the following implementation of binary trees:

    data Tree a = Nil | Branch a (Tree a) (Tree a)

We can then define `shrink` as follows:

    shrink Nil = []
    shrink (Branch x l r) =
      -- shrink Branch to Nil
      [Nil] ++
      -- shrink to subterms
      [l, r] ++
      -- recursively shrink subterms
      [Branch x' l' r' | (x', l', r') <- shrink (x, l, r)]

There are a couple of subtleties here:

- QuickCheck tries the shrinking candidates in the order they appear in the list, so we put more aggressive shrinking steps (such as replacing the whole tree by `Nil`) before smaller ones (such as recursively shrinking the subtrees).
- It is tempting to write the last line as `[Branch x' l' r' | x' <- shrink x, l' <- shrink l, r' <- shrink r]` but this is the wrong thing! It will force QuickCheck to shrink `x`, `l` and `r` in tandem, and shrinking will stop once one of the three is fully shrunk.

There is a fair bit of boilerplate in the code above. We can avoid it with the help of some generic functions; note that these only work on GHC 7.2 and above. The function `genericShrink` tries shrinking a term to all of its subterms and, failing that, recursively shrinks the subterms. Using it, we can define `shrink` as:

    shrink x = shrinkToNil x ++ genericShrink x
      where
        shrinkToNil Nil = []
        shrinkToNil (Branch _ l r) = [Nil]

`genericShrink` is a combination of `subterms`, which shrinks a term to any of its subterms, and `recursivelyShrink`, which shrinks all subterms of a term. These may be useful if you need a bit more control over shrinking than `genericShrink` gives you.

A final gotcha: we cannot define `shrink` as simply ``shrink` x = Nil:`genericShrink` x` as this shrinks `Nil` to `Nil`, and shrinking will go into an infinite loop.

If all this leaves you bewildered, you might try ``shrink` = `genericShrink`` to begin with, after deriving `Generic` for your type. However, if your data type has any special invariants, you will need to check that `genericShrink` can't break those invariants.

Instances

Arbitrary Bool |
Methods arbitrary :: Gen Bool # shrink :: Bool -> [Bool] #
Arbitrary Char |
Methods arbitrary :: Gen Char # shrink :: Char -> [Char] #
Arbitrary Double |
Methods arbitrary :: Gen Double # shrink :: Double -> [Double] #
Arbitrary Float |
Methods arbitrary :: Gen Float # shrink :: Float -> [Float] #
Arbitrary Int |
Methods arbitrary :: Gen Int # shrink :: Int -> [Int] #
Arbitrary Int8 |
Methods arbitrary :: Gen Int8 # shrink :: Int8 -> [Int8] #
Arbitrary Int16 |
Methods arbitrary :: Gen Int16 # shrink :: Int16 -> [Int16] #
Arbitrary Int32 |
Methods arbitrary :: Gen Int32 # shrink :: Int32 -> [Int32] #
Arbitrary Int64 |
Methods arbitrary :: Gen Int64 # shrink :: Int64 -> [Int64] #
Arbitrary Integer |
Methods arbitrary :: Gen Integer # shrink :: Integer -> [Integer] #
Arbitrary Ordering |
Methods arbitrary :: Gen Ordering # shrink :: Ordering -> [Ordering] #
Arbitrary Word |
Methods arbitrary :: Gen Word # shrink :: Word -> [Word] #
Arbitrary Word8 |
Methods arbitrary :: Gen Word8 # shrink :: Word8 -> [Word8] #
Arbitrary Word16 |
Methods arbitrary :: Gen Word16 # shrink :: Word16 -> [Word16] #
Arbitrary Word32 |
Methods arbitrary :: Gen Word32 # shrink :: Word32 -> [Word32] #
Arbitrary Word64 |
Methods arbitrary :: Gen Word64 # shrink :: Word64 -> [Word64] #
Arbitrary () |
Methods arbitrary :: Gen () # shrink :: () -> [()] #
Arbitrary Version | Generates `Version` with non-empty non-negative `versionBranch`, and empty `versionTags`
Methods arbitrary :: Gen Version # shrink :: Version -> [Version] #
Arbitrary Natural |
Methods arbitrary :: Gen Natural # shrink :: Natural -> [Natural] #
Arbitrary All |
Methods arbitrary :: Gen All # shrink :: All -> [All] #
Arbitrary Any |
Methods arbitrary :: Gen Any # shrink :: Any -> [Any] #
Arbitrary IntSet |
Methods arbitrary :: Gen IntSet # shrink :: IntSet -> [IntSet] #
Arbitrary a => Arbitrary [a] |
Methods arbitrary :: Gen [a] # shrink :: [a] -> [[a]] #
Arbitrary a => Arbitrary (Maybe a) |
Methods arbitrary :: Gen (Maybe a) # shrink :: Maybe a -> [Maybe a] #
Integral a => Arbitrary (Ratio a) |
Methods arbitrary :: Gen (Ratio a) # shrink :: Ratio a -> [Ratio a] #
Arbitrary a => Arbitrary (Identity a) |
Methods arbitrary :: Gen (Identity a) # shrink :: Identity a -> [Identity a] #
Arbitrary a => Arbitrary (NonEmpty a) |
Methods arbitrary :: Gen (NonEmpty a) # shrink :: NonEmpty a -> [NonEmpty a] #
HasResolution a => Arbitrary (Fixed a) |
Methods arbitrary :: Gen (Fixed a) # shrink :: Fixed a -> [Fixed a] #
(RealFloat a, Arbitrary a) => Arbitrary (Complex a) |
Methods arbitrary :: Gen (Complex a) # shrink :: Complex a -> [Complex a] #
Arbitrary a => Arbitrary (ZipList a) |
Methods arbitrary :: Gen (ZipList a) # shrink :: ZipList a -> [ZipList a] #
Arbitrary a => Arbitrary (Dual a) |
Methods arbitrary :: Gen (Dual a) # shrink :: Dual a -> [Dual a] #
(Arbitrary a, CoArbitrary a) => Arbitrary (Endo a) |
Methods arbitrary :: Gen (Endo a) # shrink :: Endo a -> [Endo a] #
Arbitrary a => Arbitrary (Sum a) |
Methods arbitrary :: Gen (Sum a) # shrink :: Sum a -> [Sum a] #
Arbitrary a => Arbitrary (Product a) |
Methods arbitrary :: Gen (Product a) # shrink :: Product a -> [Product a] #
Arbitrary a => Arbitrary (First a) |
Methods arbitrary :: Gen (First a) # shrink :: First a -> [First a] #
Arbitrary a => Arbitrary (Last a) |
Methods arbitrary :: Gen (Last a) # shrink :: Last a -> [Last a] #
Arbitrary a => Arbitrary (IntMap a) |
Methods arbitrary :: Gen (IntMap a) # shrink :: IntMap a -> [IntMap a] #
Arbitrary a => Arbitrary (Seq a) |
Methods arbitrary :: Gen (Seq a) # shrink :: Seq a -> [Seq a] #
(Ord a, Arbitrary a) => Arbitrary (Set a) |
Methods arbitrary :: Gen (Set a) # shrink :: Set a -> [Set a] #
(CoArbitrary a, Arbitrary b) => Arbitrary (a -> b) |
Methods arbitrary :: Gen (a -> b) # shrink :: (a -> b) -> [a -> b] #
(Arbitrary a, Arbitrary b) => Arbitrary (Either a b) |
Methods arbitrary :: Gen (Either a b) # shrink :: Either a b -> [Either a b] #
(Arbitrary a, Arbitrary b) => Arbitrary (a, b) |
Methods arbitrary :: Gen (a, b) # shrink :: (a, b) -> [(a, b)] #
(Ord k, Arbitrary k, Arbitrary v) => Arbitrary (Map k v) |
Methods arbitrary :: Gen (Map k v) # shrink :: Map k v -> [Map k v] #
(Arbitrary a, Arbitrary b, Arbitrary c) => Arbitrary (a, b, c) |
Methods arbitrary :: Gen (a, b, c) # shrink :: (a, b, c) -> [(a, b, c)] #
Arbitrary a => Arbitrary (Const * a b) |
Methods arbitrary :: Gen (Const * a b) # shrink :: Const * a b -> [Const * a b] #
Arbitrary (f a) => Arbitrary (Alt * f a) |
Methods arbitrary :: Gen (Alt * f a) # shrink :: Alt * f a -> [Alt * f a] #
Arbitrary a => Arbitrary (Constant * a b) |
Methods arbitrary :: Gen (Constant * a b) # shrink :: Constant * a b -> [Constant * a b] #
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d) => Arbitrary (a, b, c, d) |
Methods arbitrary :: Gen (a, b, c, d) # shrink :: (a, b, c, d) -> [(a, b, c, d)] #
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e) => Arbitrary (a, b, c, d, e) |
Methods arbitrary :: Gen (a, b, c, d, e) # shrink :: (a, b, c, d, e) -> [(a, b, c, d, e)] #
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e, Arbitrary f) => Arbitrary (a, b, c, d, e, f) |
Methods arbitrary :: Gen (a, b, c, d, e, f) # shrink :: (a, b, c, d, e, f) -> [(a, b, c, d, e, f)] #
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e, Arbitrary f, Arbitrary g) => Arbitrary (a, b, c, d, e, f, g) |
Methods arbitrary :: Gen (a, b, c, d, e, f, g) # shrink :: (a, b, c, d, e, f, g) -> [(a, b, c, d, e, f, g)] #
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e, Arbitrary f, Arbitrary g, Arbitrary h) => Arbitrary (a, b, c, d, e, f, g, h) |
Methods arbitrary :: Gen (a, b, c, d, e, f, g, h) # shrink :: (a, b, c, d, e, f, g, h) -> [(a, b, c, d, e, f, g, h)] #
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e, Arbitrary f, Arbitrary g, Arbitrary h, Arbitrary i) => Arbitrary (a, b, c, d, e, f, g, h, i) |
Methods arbitrary :: Gen (a, b, c, d, e, f, g, h, i) # shrink :: (a, b, c, d, e, f, g, h, i) -> [(a, b, c, d, e, f, g, h, i)] #
(Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d, Arbitrary e, Arbitrary f, Arbitrary g, Arbitrary h, Arbitrary i, Arbitrary j) => Arbitrary (a, b, c, d, e, f, g, h, i, j) |
Methods arbitrary :: Gen (a, b, c, d, e, f, g, h, i, j) # shrink :: (a, b, c, d, e, f, g, h, i, j) -> [(a, b, c, d, e, f, g, h, i, j)] #

module Test.QuickCheck.Gen

# Internals

class Testable a where Source #

Minimal complete definition

toProperty

Methods

toProperty :: a -> WaiProperty Source #

Instances

Testable WaiExpectation Source # |
Methods toProperty :: WaiExpectation -> WaiProperty Source #
Testable WaiProperty Source # |
Methods toProperty :: WaiProperty -> WaiProperty Source #
(Arbitrary a, Show a, Testable prop) => Testable (a -> prop) Source # |
Methods toProperty :: (a -> prop) -> WaiProperty Source #

data WaiProperty Source #

Constructors

WaiProperty |

Fields

- unWaiProperty :: Application -> Property

Instances

Testable WaiProperty Source # |
Methods toProperty :: WaiProperty -> WaiProperty Source #