# Catchy combinators for HUnit

(inspired by [ScalaTest's ShouldMatchers](http://www.scalatest.org/))

The three main primitives are `shouldBe`, `shouldSatisfy` and
`shouldThrow`. They can be used with
[HUnit](http://hackage.haskell.org/package/HUnit), or any framework that
integrates with HUnit, like
[test-framework](http://hackage.haskell.org/package/test-framework) or
[Hspec](http://hackage.haskell.org/package/hspec).

## An introductory example

Here is an example that uses Hspec. It's a partial specification of
itself.

~~~ {.haskell .literate}
import Test.Hspec
import Control.Exception

main :: IO ()
main = hspec $ do
  describe "shouldBe" $ do
    it "asserts equality" $ do
      "foo" `shouldBe` "foo"

  describe "shouldSatisfy" $ do
    it "asserts that a predicate holds" $ do
      "bar" `shouldSatisfy` (not . null)

  describe "shouldThrow" $ do
    it "asserts that an exception is thrown" $ do
      evaluate (1 `div` 0 :: Int) `shouldThrow` (== DivideByZero)
~~~

## shouldBe

`shouldBe` is just an alias for HUnit's `@?=`.

## shouldSatisfy

`shouldSatisfy` asserts that some predicate holds for a given value.

~~~ {.haskell}
"bar" `shouldSatisfy` (not . null)
~~~

It is similar to HUnit's `assertBool`, but gives a useful error message.

    >>> 23 `shouldSatisfy` (> 42)
    *** Exception: HUnitFailure "23 did not satisfy predicate!"

## shouldReturn

`shouldReturn` asserts that an action returns a given value.

~~~ {.haskell}
launchMissiles `shouldReturn` Left "permission error"
~~~

## shouldThrow

`shouldThrow` asserts that an exception is thrown. The precise nature of
that exception is described with a `Selector`.

~~~ {.haskell}
error "foobar" `shouldThrow` anyException
~~~

A `Selector` is a predicate, it can simultaneously constrain the type
and value of an exception.

~~~ {.haskell}
throw DivideByZero `shouldThrow` (== DivideByZero)
~~~

To select all exceptions of a given type, `const True` can be used.

~~~ {.haskell}
error "foobar" `shouldThrow` (const True :: Selector ErrorCall)
~~~

For convenience, predefined selectors for some standard exceptions are
provided.

~~~ {.haskell}
error "foobar" `shouldThrow` anyErrorCall
~~~

Some exceptions (like `ErrorCall`) have no `Eq` instance, so checking
for a specific value requires pattern matching.

~~~ {.haskell}
error "foobar" `shouldThrow` (\e -> case e of
    ErrorCall "foobar" -> True
    _ -> False
    )
~~~

For such exceptions, combinators that construct selectors are provided.
Each combinator corresponds to a constructor; it takes the same
arguments, and has the same name (but starting with a lower-case
letter).

~~~ {.haskell}
error "foobar" `shouldThrow` errorCall "foobar"
~~~
