# 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"
~~~