Blame src/Test/Hspec/Expectations.hs

Packit 6375e3
{-# LANGUAGE CPP #-}
Packit 6375e3
{-# LANGUAGE ConstraintKinds #-}
Packit 6375e3
{-# LANGUAGE KindSignatures #-}
Packit 6375e3
{-# LANGUAGE ImplicitParams #-}
Packit 6375e3
-- |
Packit 6375e3
-- Introductory documentation: <https://github.com/sol/hspec-expectations#readme>
Packit 6375e3
module Test.Hspec.Expectations (
Packit 6375e3
Packit 6375e3
-- * Setting expectations
Packit 6375e3
  Expectation
Packit 6375e3
, expectationFailure
Packit 6375e3
, shouldBe
Packit 6375e3
, shouldSatisfy
Packit 6375e3
, shouldStartWith
Packit 6375e3
, shouldEndWith
Packit 6375e3
, shouldContain
Packit 6375e3
, shouldMatchList
Packit 6375e3
, shouldReturn
Packit 6375e3
Packit 6375e3
, shouldNotBe
Packit 6375e3
, shouldNotSatisfy
Packit 6375e3
, shouldNotContain
Packit 6375e3
, shouldNotReturn
Packit 6375e3
Packit 6375e3
-- * Expecting exceptions
Packit 6375e3
, shouldThrow
Packit 6375e3
Packit 6375e3
-- ** Selecting exceptions
Packit 6375e3
, Selector
Packit 6375e3
Packit 6375e3
-- ** Predefined type-based selectors
Packit 6375e3
-- |
Packit 6375e3
-- There are predefined selectors for some standard exceptions.  Each selector
Packit 6375e3
-- is just @const True@ with an appropriate type.
Packit 6375e3
, anyException
Packit 6375e3
, anyErrorCall
Packit 6375e3
, anyIOException
Packit 6375e3
, anyArithException
Packit 6375e3
Packit 6375e3
-- ** Combinators for defining value-based selectors
Packit 6375e3
-- |
Packit 6375e3
-- Some exceptions (most prominently `ErrorCall`) have no `Eq` instance.
Packit 6375e3
-- Selecting a specific value would require pattern matching.
Packit 6375e3
--
Packit 6375e3
-- For such exceptions, combinators that construct selectors are provided.
Packit 6375e3
-- Each combinator corresponds to a constructor; it takes the same arguments,
Packit 6375e3
-- and has the same name (but starting with a lower-case letter).
Packit 6375e3
, errorCall
Packit 6375e3
Packit 6375e3
-- * Re-exports
Packit 6375e3
, HasCallStack
Packit 6375e3
) where
Packit 6375e3
Packit 6375e3
import qualified Test.HUnit
Packit 6375e3
import           Test.HUnit ((@?=))
Packit 6375e3
import           Control.Exception
Packit 6375e3
import           Data.Typeable
Packit 6375e3
import           Data.List
Packit 6375e3
Packit 6375e3
import           Control.Monad (unless)
Packit 6375e3
Packit 6375e3
import           Test.Hspec.Expectations.Matcher
Packit 6375e3
Packit 6375e3
#if MIN_VERSION_HUnit(1,4,0)
Packit 6375e3
import           Data.CallStack (HasCallStack)
Packit 6375e3
#else
Packit 6375e3
#if MIN_VERSION_base(4,8,1)
Packit 6375e3
import qualified GHC.Stack as GHC
Packit 6375e3
type HasCallStack = (?loc :: GHC.CallStack)
Packit 6375e3
#else
Packit 6375e3
import GHC.Exts (Constraint)
Packit 6375e3
type HasCallStack = (() :: Constraint)
Packit 6375e3
#endif
Packit 6375e3
#endif
Packit 6375e3
Packit 6375e3
type Expectation = Test.HUnit.Assertion
Packit 6375e3
Packit 6375e3
expectationFailure :: HasCallStack => String -> Expectation
Packit 6375e3
expectationFailure = Test.HUnit.assertFailure
Packit 6375e3
Packit 6375e3
expectTrue :: HasCallStack => String -> Bool -> Expectation
Packit 6375e3
expectTrue msg b = unless b (expectationFailure msg)
Packit 6375e3
Packit 6375e3
infix 1 `shouldBe`, `shouldSatisfy`, `shouldStartWith`, `shouldEndWith`, `shouldContain`, `shouldMatchList`, `shouldReturn`, `shouldThrow`
Packit 6375e3
infix 1 `shouldNotBe`, `shouldNotSatisfy`, `shouldNotContain`, `shouldNotReturn`
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @actual \`shouldBe\` expected@ sets the expectation that @actual@ is equal
Packit 6375e3
-- to @expected@.
Packit 6375e3
shouldBe :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation
Packit 6375e3
actual `shouldBe` expected = actual @?= expected
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @v \`shouldSatisfy\` p@ sets the expectation that @p v@ is @True@.
Packit 6375e3
shouldSatisfy :: (HasCallStack, Show a) => a -> (a -> Bool) -> Expectation
Packit 6375e3
v `shouldSatisfy` p = expectTrue ("predicate failed on: " ++ show v) (p v)
Packit 6375e3
Packit 6375e3
compareWith :: (HasCallStack, Show a) => (a -> a -> Bool) -> String -> a -> a -> Expectation
Packit 6375e3
compareWith comparator errorDesc result expected = expectTrue errorMsg (comparator expected result)
Packit 6375e3
  where
Packit 6375e3
    errorMsg = show result ++ " " ++ errorDesc ++ " " ++ show expected
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @list \`shouldStartWith\` prefix@ sets the expectation that @list@ starts with @prefix@,
Packit 6375e3
shouldStartWith :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation
Packit 6375e3
shouldStartWith = compareWith isPrefixOf "does not start with"
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @list \`shouldEndWith\` suffix@ sets the expectation that @list@ ends with @suffix@,
Packit 6375e3
shouldEndWith :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation
Packit 6375e3
shouldEndWith = compareWith isSuffixOf "does not end with"
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @list \`shouldContain\` sublist@ sets the expectation that @sublist@ is contained,
Packit 6375e3
-- wholly and intact, anywhere in @list@.
Packit 6375e3
shouldContain :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation
Packit 6375e3
shouldContain = compareWith isInfixOf "does not contain"
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @xs \`shouldMatchList\` ys@ sets the expectation that @xs@ has the same
Packit 6375e3
-- elements that @ys@ has, possibly in another order
Packit 6375e3
shouldMatchList :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation
Packit 6375e3
xs `shouldMatchList` ys = maybe (return ()) expectationFailure (matchList xs ys)
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @action \`shouldReturn\` expected@ sets the expectation that @action@
Packit 6375e3
-- returns @expected@.
Packit 6375e3
shouldReturn :: (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
Packit 6375e3
action `shouldReturn` expected = action >>= (`shouldBe` expected)
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @actual \`shouldNotBe\` notExpected@ sets the expectation that @actual@ is not
Packit 6375e3
-- equal to @notExpected@
Packit 6375e3
shouldNotBe :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation
Packit 6375e3
actual `shouldNotBe` notExpected = expectTrue ("not expected: " ++ show actual) (actual /= notExpected)
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @v \`shouldNotSatisfy\` p@ sets the expectation that @p v@ is @False@.
Packit 6375e3
shouldNotSatisfy :: (HasCallStack, Show a) => a -> (a -> Bool) -> Expectation
Packit 6375e3
v `shouldNotSatisfy` p = expectTrue ("predicate succeeded on: " ++ show v) ((not . p) v)
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @list \`shouldNotContain\` sublist@ sets the expectation that @sublist@ is not
Packit 6375e3
-- contained anywhere in @list@.
Packit 6375e3
shouldNotContain :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation
Packit 6375e3
list `shouldNotContain` sublist = expectTrue errorMsg ((not . isInfixOf sublist) list)
Packit 6375e3
  where
Packit 6375e3
    errorMsg = show list ++ " does contain " ++ show sublist
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @action \`shouldNotReturn\` notExpected@ sets the expectation that @action@
Packit 6375e3
-- does not return @notExpected@.
Packit 6375e3
shouldNotReturn :: (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation
Packit 6375e3
action `shouldNotReturn` notExpected = action >>= (`shouldNotBe` notExpected)
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- A @Selector@ is a predicate; it can simultaneously constrain the type and
Packit 6375e3
-- value of an exception.
Packit 6375e3
type Selector a = (a -> Bool)
Packit 6375e3
Packit 6375e3
-- |
Packit 6375e3
-- @action \`shouldThrow\` selector@ sets the expectation that @action@ throws
Packit 6375e3
-- an exception.  The precise nature of the expected exception is described
Packit 6375e3
-- with a 'Selector'.
Packit 6375e3
shouldThrow :: (HasCallStack, Exception e) => IO a -> Selector e -> Expectation
Packit 6375e3
action `shouldThrow` p = do
Packit 6375e3
  r <- try action
Packit 6375e3
  case r of
Packit 6375e3
    Right _ ->
Packit 6375e3
      expectationFailure $
Packit 6375e3
        "did not get expected exception: " ++ exceptionType
Packit 6375e3
    Left e ->
Packit 6375e3
      (`expectTrue` p e) $
Packit 6375e3
        "predicate failed on expected exception: " ++ exceptionType ++ " (" ++ show e ++ ")"
Packit 6375e3
  where
Packit 6375e3
    -- a string repsentation of the expected exception's type
Packit 6375e3
    exceptionType = (show . typeOf . instanceOf) p
Packit 6375e3
      where
Packit 6375e3
        instanceOf :: Selector a -> a
Packit 6375e3
        instanceOf _ = error "Test.Hspec.Expectations.shouldThrow: broken Typeable instance"
Packit 6375e3
Packit 6375e3
anyException :: Selector SomeException
Packit 6375e3
anyException = const True
Packit 6375e3
Packit 6375e3
anyErrorCall :: Selector ErrorCall
Packit 6375e3
anyErrorCall = const True
Packit 6375e3
Packit 6375e3
errorCall :: String -> Selector ErrorCall
Packit 6375e3
#if MIN_VERSION_base(4,9,0)
Packit 6375e3
errorCall s (ErrorCallWithLocation msg _) = s == msg
Packit 6375e3
#else
Packit 6375e3
errorCall s (ErrorCall msg) = s == msg
Packit 6375e3
#endif
Packit 6375e3
Packit 6375e3
anyIOException :: Selector IOException
Packit 6375e3
anyIOException = const True
Packit 6375e3
Packit 6375e3
anyArithException :: Selector ArithException
Packit 6375e3
anyArithException = const True