module Test.Hspec.Expectations (
Expectation
, expectationFailure
, shouldBe
, shouldSatisfy
, shouldContain
, shouldMatchList
, shouldReturn
, shouldThrow
, Selector
, anyException
, anyErrorCall
, anyIOException
, anyArithException
, errorCall
) where
import Test.HUnit (Assertion, (@?=), assertBool, assertFailure)
import Control.Exception
import Data.Typeable
import Data.List (isInfixOf)
import Test.Hspec.Expectations.Matcher
type Expectation = Assertion
expectationFailure :: String -> Expectation
expectationFailure = assertFailure
infix 1 `shouldBe`, `shouldSatisfy`, `shouldContain`, `shouldMatchList`, `shouldReturn`, `shouldThrow`
shouldBe :: (Show a, Eq a) => a -> a -> Expectation
actual `shouldBe` expected = actual @?= expected
shouldSatisfy :: (Show a) => a -> (a -> Bool) -> Expectation
v `shouldSatisfy` p = assertBool ("predicate failed on: " ++ show v) (p v)
shouldContain :: (Show a, Eq a) => [a] -> [a] -> Expectation
list `shouldContain` sublist = assertBool errorMsg (sublist `isInfixOf` list)
where
errorMsg = show list ++ " doesn't contain " ++ show sublist
shouldMatchList :: (Show a, Eq a) => [a] -> [a] -> Expectation
xs `shouldMatchList` ys = maybe (return ()) assertFailure (matchList xs ys)
shouldReturn :: (Show a, Eq a) => IO a -> a -> Expectation
action `shouldReturn` expected = action >>= (`shouldBe` expected)
type Selector a = (a -> Bool)
shouldThrow :: Exception e => IO a -> Selector e -> Expectation
action `shouldThrow` p = do
r <- try action
case r of
Right _ ->
expectationFailure $
"did not get expected exception: " ++ exceptionType
Left e ->
(`assertBool` p e) $
"predicate failed on expected exception: " ++ exceptionType ++ " (" ++ show e ++ ")"
where
exceptionType = (show . typeOf . instanceOf) p
where
instanceOf :: Selector a -> a
instanceOf _ = error "Test.Hspec.Expectations.shouldThrow: broken Typeable instance"
anyException :: Selector SomeException
anyException = const True
anyErrorCall :: Selector ErrorCall
anyErrorCall = const True
errorCall :: String -> Selector ErrorCall
errorCall s (ErrorCall msg) = s == msg
anyIOException :: Selector IOException
anyIOException = const True
anyArithException :: Selector ArithException
anyArithException = const True