packages feed

hspec-expectations 0.6.0.1 → 0.8.4

raw patch · 11 files changed

Files

LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2011-2013 Simon Hengel <sol@typeful.net>+Copyright (c) 2011-2023 Simon Hengel <sol@typeful.net>  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
− README.lhs
@@ -1,107 +0,0 @@-# 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"-~~~
hspec-expectations.cabal view
@@ -1,57 +1,62 @@+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.35.2.+--+-- see: https://github.com/sol/hpack+ name:             hspec-expectations-version:          0.6.0.1+version:          0.8.4 synopsis:         Catchy combinators for HUnit-description:      Catchy combinators for HUnit: <https://github.com/sol/hspec-expectations#readme>+description:      Catchy combinators for HUnit: <https://github.com/hspec/hspec-expectations#readme>+bug-reports:      https://github.com/hspec/hspec-expectations/issues license:          MIT license-file:     LICENSE-copyright:        (c) 2011-2013 Simon Hengel+copyright:        (c) 2011-2023 Simon Hengel author:           Simon Hengel <sol@typeful.net> maintainer:       Simon Hengel <sol@typeful.net> build-type:       Simple category:         Testing-cabal-version:    >= 1.8-homepage:         https://github.com/sol/hspec-expectations#readme+homepage:         https://github.com/hspec/hspec-expectations#readme  source-repository head   type: git-  location: https://github.com/sol/hspec-expectations+  location: https://github.com/hspec/hspec-expectations  library-  ghc-options:-      -Wall-  build-depends:-      base < 4.8-    , HUnit   hs-source-dirs:       src+  ghc-options: -Wall+  build-depends:+      HUnit+    , base ==4.*+    , call-stack   exposed-modules:       Test.Hspec.Expectations-    , Test.Hspec.Expectations.Contrib+      Test.Hspec.Expectations.Contrib+  other-modules:+      Test.Hspec.Expectations.Matcher+      Paths_hspec_expectations+  default-language: Haskell2010  test-suite spec-  main-is:-      Spec.hs-  type:-      exitcode-stdio-1.0-  ghc-options:-      -Wall -Werror+  type: exitcode-stdio-1.0+  main-is: Spec.hs   hs-source-dirs:+      test       src-    , test-  build-depends:-      base-    , HUnit-    , silently-    , hspec       >= 1.3--test-suite readme-  type:-      exitcode-stdio-1.0-  ghc-options:-      -Wall -Werror -pgmL markdown-unlit -optL haskell+literate-  main-is:-      README.lhs+  ghc-options: -Wall   build-depends:-      base-    , hspec       >= 1.3-    , markdown-unlit+      HUnit >=1.5.0.0+    , base ==4.*+    , call-stack+    , nanospec+  other-modules:+      Helper+      Test.Hspec.Expectations.ContribSpec+      Test.Hspec.Expectations.MatcherSpec+      Test.Hspec.ExpectationsSpec+      Test.Hspec.Expectations+      Test.Hspec.Expectations.Contrib+      Test.Hspec.Expectations.Matcher+      Paths_hspec_expectations+  default-language: Haskell2010
src/Test/Hspec/Expectations.hs view
@@ -1,5 +1,9 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE ImplicitParams #-} -- |--- Introductory documentation: <https://github.com/sol/hspec-expectations#readme>+-- Introductory documentation: <https://github.com/hspec/hspec-expectations#readme> module Test.Hspec.Expectations (  -- * Setting expectations@@ -7,10 +11,17 @@ , expectationFailure , shouldBe , shouldSatisfy+, shouldStartWith+, shouldEndWith , shouldContain , shouldMatchList , shouldReturn +, shouldNotBe+, shouldNotSatisfy+, shouldNotContain+, shouldNotReturn+ -- * Expecting exceptions , shouldThrow @@ -35,55 +46,114 @@ -- Each combinator corresponds to a constructor; it takes the same arguments, -- and has the same name (but starting with a lower-case letter). , errorCall++-- * Re-exports+, HasCallStack ) where -import           Test.HUnit (Assertion, (@?=), assertBool, assertFailure)+import qualified Test.HUnit+import           Test.HUnit ((@?=)) import           Control.Exception import           Data.Typeable-import           Data.List ((\\), isInfixOf)+import           Data.List -type Expectation = Assertion+import           Control.Monad (unless) --- | This is just an alias for HUnit's `assertFailure`.-expectationFailure :: String -> Expectation-expectationFailure = assertFailure+import           Test.Hspec.Expectations.Matcher -infix 1 `shouldBe`, `shouldSatisfy`, `shouldContain`, `shouldMatchList`, `shouldReturn`, `shouldThrow`+#if MIN_VERSION_HUnit(1,4,0)+import           Data.CallStack (HasCallStack)+#else+#if MIN_VERSION_base(4,8,1)+import qualified GHC.Stack as GHC+type HasCallStack = (?loc :: GHC.CallStack)+#else+import GHC.Exts (Constraint)+type HasCallStack = (() :: Constraint)+#endif+#endif +type Expectation = Test.HUnit.Assertion++expectationFailure :: HasCallStack => String -> Expectation+expectationFailure = Test.HUnit.assertFailure++expectTrue :: HasCallStack => String -> Bool -> Expectation+expectTrue msg b = unless b (expectationFailure msg)++infix 1 `shouldBe`, `shouldSatisfy`, `shouldStartWith`, `shouldEndWith`, `shouldContain`, `shouldMatchList`, `shouldReturn`, `shouldThrow`+infix 1 `shouldNotBe`, `shouldNotSatisfy`, `shouldNotContain`, `shouldNotReturn`+ -- | -- @actual \`shouldBe\` expected@ sets the expectation that @actual@ is equal--- to @expected@ (this is just an alias for `@?=`).-shouldBe :: (Show a, Eq a) => a -> a -> Expectation+-- to @expected@.+shouldBe :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation actual `shouldBe` expected = actual @?= expected  -- | -- @v \`shouldSatisfy\` p@ sets the expectation that @p v@ is @True@.-shouldSatisfy :: (Show a) => a -> (a -> Bool) -> Expectation-v `shouldSatisfy` p = assertBool ("predicate failed on: " ++ show v) (p v)+shouldSatisfy :: (HasCallStack, Show a) => a -> (a -> Bool) -> Expectation+v `shouldSatisfy` p = expectTrue ("predicate failed on: " ++ show v) (p v) +compareWith :: (HasCallStack, Show a) => (a -> a -> Bool) -> String -> a -> a -> Expectation+compareWith comparator errorDesc result expected = expectTrue errorMsg (comparator expected result)+  where+    errorMsg = show result ++ " " ++ errorDesc ++ " " ++ show expected+ -- |+-- @list \`shouldStartWith\` prefix@ sets the expectation that @list@ starts with @prefix@,+shouldStartWith :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation+shouldStartWith = compareWith isPrefixOf "does not start with"++-- |+-- @list \`shouldEndWith\` suffix@ sets the expectation that @list@ ends with @suffix@,+shouldEndWith :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation+shouldEndWith = compareWith isSuffixOf "does not end with"++-- | -- @list \`shouldContain\` sublist@ sets the expectation that @sublist@ is contained, -- wholly and intact, anywhere in @list@.-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+shouldContain :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation+shouldContain = compareWith isInfixOf "does not contain"  -- | -- @xs \`shouldMatchList\` ys@ sets the expectation that @xs@ has the same -- elements that @ys@ has, possibly in another order-shouldMatchList :: (Show a, Eq a) => [a] -> [a] -> Expectation-xs `shouldMatchList` ys = assertBool errorMsg (all null [xs \\ ys, ys \\ xs])-  where-    errorMsg = show ys ++ " is not a permutation of " ++ show xs+shouldMatchList :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation+xs `shouldMatchList` ys = maybe (return ()) expectationFailure (matchList xs ys)  -- | -- @action \`shouldReturn\` expected@ sets the expectation that @action@ -- returns @expected@.-shouldReturn :: (Show a, Eq a) => IO a -> a -> Expectation+shouldReturn :: (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation action `shouldReturn` expected = action >>= (`shouldBe` expected)  -- |+-- @actual \`shouldNotBe\` notExpected@ sets the expectation that @actual@ is not+-- equal to @notExpected@+shouldNotBe :: (HasCallStack, Show a, Eq a) => a -> a -> Expectation+actual `shouldNotBe` notExpected = expectTrue ("not expected: " ++ show actual) (actual /= notExpected)++-- |+-- @v \`shouldNotSatisfy\` p@ sets the expectation that @p v@ is @False@.+shouldNotSatisfy :: (HasCallStack, Show a) => a -> (a -> Bool) -> Expectation+v `shouldNotSatisfy` p = expectTrue ("predicate succeeded on: " ++ show v) ((not . p) v)++-- |+-- @list \`shouldNotContain\` sublist@ sets the expectation that @sublist@ is not+-- contained anywhere in @list@.+shouldNotContain :: (HasCallStack, Show a, Eq a) => [a] -> [a] -> Expectation+list `shouldNotContain` sublist = expectTrue errorMsg ((not . isInfixOf sublist) list)+  where+    errorMsg = show list ++ " does contain " ++ show sublist++-- |+-- @action \`shouldNotReturn\` notExpected@ sets the expectation that @action@+-- does not return @notExpected@.+shouldNotReturn :: (HasCallStack, Show a, Eq a) => IO a -> a -> Expectation+action `shouldNotReturn` notExpected = action >>= (`shouldNotBe` notExpected)++-- | -- A @Selector@ is a predicate; it can simultaneously constrain the type and -- value of an exception. type Selector a = (a -> Bool)@@ -92,7 +162,7 @@ -- @action \`shouldThrow\` selector@ sets the expectation that @action@ throws -- an exception.  The precise nature of the expected exception is described -- with a 'Selector'.-shouldThrow :: Exception e => IO a -> Selector e -> Expectation+shouldThrow :: (HasCallStack, Exception e) => IO a -> Selector e -> Expectation action `shouldThrow` p = do   r <- try action   case r of@@ -100,10 +170,10 @@       expectationFailure $         "did not get expected exception: " ++ exceptionType     Left e ->-      (`assertBool` p e) $-        "predicate failed on expected exception: " ++ exceptionType ++ " (" ++ show e ++ ")"+      (`expectTrue` p e) $+        "predicate failed on expected exception: " ++ exceptionType ++ "\n" ++ show e   where-    -- a string repsentation of the expected exception's type+    -- a string representation of the expected exception's type     exceptionType = (show . typeOf . instanceOf) p       where         instanceOf :: Selector a -> a@@ -116,7 +186,11 @@ anyErrorCall = const True  errorCall :: String -> Selector ErrorCall+#if MIN_VERSION_base(4,9,0)+errorCall s (ErrorCallWithLocation msg _) = s == msg+#else errorCall s (ErrorCall msg) = s == msg+#endif  anyIOException :: Selector IOException anyIOException = const True
src/Test/Hspec/Expectations/Contrib.hs view
@@ -1,54 +1,60 @@+{-# LANGUAGE CPP #-} -- | -- Experimental combinators, that may become part of the main distribution, if -- they turn out to be useful for a wider audience. module Test.Hspec.Expectations.Contrib (--- * Additional combinators for setting expectations-  shouldNotBe-, shouldNotSatisfy-, shouldNotReturn-, shouldNotContain- -- * Predicates -- | (useful in combination with `shouldSatisfy`)-, isLeft+  isLeft , isRight++-- * Annotating expectations+, annotate ) where -import Test.Hspec.Expectations-import Test.HUnit (assertBool)-import Data.List (isInfixOf)+import Control.Exception+import Test.HUnit.Lang (HUnitFailure(..), FailureReason(..)) +#if MIN_VERSION_base(4,7,0)+import Data.Either+#else+ isLeft :: Either a b -> Bool+{-# DEPRECATED isLeft "use Data.Either.Compat.isLeft from package base-compat instead" #-} isLeft (Left  _) = True isLeft (Right _) = False  isRight :: Either a b -> Bool+{-# DEPRECATED isRight "use Data.Either.Compat.isRight from package base-compat instead" #-} isRight (Left  _) = False isRight (Right _) = True--infix 1 `shouldNotBe`, `shouldNotSatisfy`, `shouldNotContain`, `shouldNotReturn`---- |--- @actual \`shouldNotBe\` notExpected@ sets the expectation that @actual@ is not--- equal to @notExpected@-shouldNotBe :: (Show a, Eq a) => a -> a -> Expectation-actual `shouldNotBe` notExpected = assertBool ("not expected: " ++ show actual) (actual /= notExpected)---- |--- @v \`shouldNotSatisfy\` p@ sets the expectation that @p v@ is @False@.-shouldNotSatisfy :: (Show a) => a -> (a -> Bool) -> Expectation-v `shouldNotSatisfy` p = assertBool ("predicate succeded on: " ++ show v) ((not . p) v)+#endif  -- |--- @list \`shouldNotContain\` sublist@ sets the expectation that @sublist@ is not--- contained anywhere in the second.-shouldNotContain :: (Show a, Eq a) => [a] -> [a] -> Expectation-list `shouldNotContain` sublist = assertBool errorMsg ((not . isInfixOf sublist) list)+-- If you have a test case that has multiple assertions, you can use the+-- 'annotate' function to provide a string message that will be attached to+-- the 'Expectation'.+--+-- @+-- describe "annotate" $ do+--   it "adds the message" $ do+--     annotate "obvious falsehood" $ do+--       True `shouldBe` False+--+-- ========>+--+-- 1) annotate, adds the message+--       obvious falsehood+--       expected: False+--        but got: True+-- @+--+-- @since 0.8.3+annotate :: String -> IO a -> IO a+annotate message = handle $ \ (HUnitFailure loc reason) -> throwIO . HUnitFailure loc $ case reason of+  Reason err -> Reason $ addMessage err+  ExpectedButGot err expected got -> ExpectedButGot (Just $ maybe message addMessage err) expected got   where-    errorMsg = show list ++ " does contain " ++ show sublist---- |--- @action \`shouldNotReturn\` notExpected@ sets the expectation that @action@--- does not return @notExpected@.-shouldNotReturn :: (Show a, Eq a) => IO a -> a -> Expectation-action `shouldNotReturn` notExpected = action >>= (`shouldNotBe` notExpected)+    addMessage err+      | null err = message+      | otherwise = message ++ "\n" ++ err
+ src/Test/Hspec/Expectations/Matcher.hs view
@@ -0,0 +1,26 @@+module Test.Hspec.Expectations.Matcher (matchList) where++import           Prelude hiding (showList)+import           Data.List++matchList :: (Show a, Eq a) => [a] -> [a] -> Maybe String+xs `matchList` ys+  | null extra && null missing = Nothing+  | otherwise = Just (err "")+  where+    extra   = xs \\ ys+    missing = ys \\ xs++    msgAndList msg zs = showString msg . showList zs . showString "\n"+    optMsgList msg zs = if null zs then id else msgAndList msg zs++    err :: ShowS+    err =+        showString "Actual list is not a permutation of expected list!\n"+      . msgAndList "  expected elements: " ys+      . msgAndList "  actual elements:   " xs+      . optMsgList "  missing elements:  " missing+      . optMsgList "  extra elements:    " extra++showList :: Show a => [a] -> ShowS+showList xs = showChar '[' . foldr (.) (showChar ']') (intersperse (showString ", ") $ map shows xs)
+ test/Helper.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE FlexibleContexts #-}++module Helper where++import           Test.HUnit.Lang+import           Data.CallStack++-- note: this function expects the callstacks to have identical line+-- numbers, so you need to be careful to call expectationFailed on the same+-- line that you throw any exceptions+expectationFailed :: HasCallStack => FailureReason -> HUnitFailure -> Bool+expectationFailed msg (HUnitFailure l m) = m == msg && (fmap setColumn l) == (fmap setColumn location)+  where+    location = case reverse callStack of+      [] -> Nothing+      (_, loc) : _ -> Just loc+    location :: Maybe SrcLoc++    setColumn loc_ = loc_{srcLocStartCol = 0, srcLocEndCol = 0}
test/Spec.hs view
@@ -1,1 +1,14 @@-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}+module Main where++import Test.Hspec++import qualified Test.Hspec.ExpectationsSpec+import qualified Test.Hspec.Expectations.MatcherSpec++spec :: Spec+spec = do+  describe "Test.Hspec.ExpectationsSpec" Test.Hspec.ExpectationsSpec.spec+  describe "Test.Hspec.Expectations.MatcherSpec" Test.Hspec.Expectations.MatcherSpec.spec++main :: IO ()+main = hspec spec
+ test/Test/Hspec/Expectations/ContribSpec.hs view
@@ -0,0 +1,30 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+module Test.Hspec.Expectations.ContribSpec (spec) where++import           Helper++import           Test.HUnit.Lang+import           Test.Hspec (Spec, describe, it)++import           Test.Hspec.Expectations+import           Test.Hspec.Expectations.Contrib++spec :: Spec+spec = do+  describe "annotate" $ do+    it "does not affect the running of a successful test" $ do+      annotate "obviously correct" $+        True `shouldBe` True++    it "provides a message on expectation failure" $ do+      (annotate "obvious falsehood" $ True `shouldBe` False) `shouldThrow` expectationFailed (ExpectedButGot (Just "obvious falsehood") (show False) (show True))++    it "nests messages using newlines" $ do+      let msg0 = "obvious falsehood"+          msg1 = "welp"+          msgs = msg0 ++ "\n" ++ msg1+      (annotate msg0 $ annotate msg1 $ True `shouldBe` False) `shouldThrow` expectationFailed (ExpectedButGot (Just msgs) (show False) (show True))++    it "appends messages to Reason" $ do+      (annotate "welp" $ True `shouldSatisfy` (== False)) `shouldThrow` expectationFailed (Reason "welp\npredicate failed on: True")
+ test/Test/Hspec/Expectations/MatcherSpec.hs view
@@ -0,0 +1,34 @@+module Test.Hspec.Expectations.MatcherSpec (main, spec) where++import           Test.Hspec++import           Test.Hspec.Expectations.Matcher++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "matchList" $ do+    it "succeeds if arguments are empty lists" $ do+      matchList [] ([] :: [Int]) `shouldBe` Nothing++    it "succeeds if arguments are equal up to permutation" $ do+      matchList [1, 2, 2, 3] [3, 2, 1, 2 :: Int] `shouldBe` Nothing++    context "when arguments are not equal up to permutation" $ do+      it "shows extra elements" $ do+        [1, 2, 2, 3] `matchList` [1, 2, 3 :: Int] `shouldBe` (Just . unlines) [+            "Actual list is not a permutation of expected list!"+          , "  expected elements: [1, 2, 3]"+          , "  actual elements:   [1, 2, 2, 3]"+          , "  extra elements:    [2]"+          ]++      it "shows missing elements" $ do+        [1, 2, 3] `matchList` [1, 2, 2, 3 :: Int] `shouldBe` (Just . unlines) [+            "Actual list is not a permutation of expected list!"+          , "  expected elements: [1, 2, 2, 3]"+          , "  actual elements:   [1, 2, 3]"+          , "  missing elements:  [2]"+          ]
+ test/Test/Hspec/ExpectationsSpec.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+module Test.Hspec.ExpectationsSpec (spec) where++import           Helper++import           Control.Exception+import           Test.HUnit.Lang+import           Test.Hspec (Spec, describe, it)++import           Test.Hspec.Expectations++spec :: Spec+spec = do+  describe "shouldBe" $ do+    it "succeeds if arguments are equal" $ do+      "foo" `shouldBe` "foo"++    it "fails if arguments are not equal" $ do+      ("foo" `shouldBe` "bar") `shouldThrow` expectationFailed (ExpectedButGot Nothing "\"bar\"" "\"foo\"")++  describe "shouldSatisfy" $ do+    it "succeeds if value satisfies predicate" $ do+      "" `shouldSatisfy` null++    it "fails if value does not satisfy predicate" $ do+      ("foo" `shouldSatisfy` null) `shouldThrow` expectationFailed (Reason "predicate failed on: \"foo\"")++  describe "shouldReturn" $ do+    it "succeeds if arguments represent equal values" $ do+      return "foo" `shouldReturn` "foo"++    it "fails if arguments do not represent equal values" $ do+      (return "foo" `shouldReturn` "bar") `shouldThrow` expectationFailed (ExpectedButGot Nothing "\"bar\"" "\"foo\"")++  describe "shouldStartWith" $ do+    it "succeeds if second is prefix of first" $ do+      "hello world" `shouldStartWith` "hello"++    it "fails if second is not prefix of first" $ do+      ("hello world" `shouldStartWith` "world") `shouldThrow` expectationFailed (Reason "\"hello world\" does not start with \"world\"")++  describe "shouldEndWith" $ do+    it "succeeds if second is suffix of first" $ do+      "hello world" `shouldEndWith` "world"++    it "fails if second is not suffix of first" $ do+      ("hello world" `shouldEndWith` "hello") `shouldThrow` expectationFailed (Reason "\"hello world\" does not end with \"hello\"")++  describe "shouldContain" $ do+    it "succeeds if second argument is contained in the first" $ do+      "I'm an hello world message" `shouldContain` "an hello"++    it "fails if first argument does not contain the second" $ do+      ("foo" `shouldContain` "bar") `shouldThrow` expectationFailed (Reason "\"foo\" does not contain \"bar\"")++  describe "shouldNotBe" $ do+    it "succeeds if arguments are not equal" $ do+      "foo" `shouldNotBe` "bar"++    it "fails if arguments are equal" $ do+      ("foo" `shouldNotBe` "foo") `shouldThrow` expectationFailed (Reason "not expected: \"foo\"")++  describe "shouldNotSatisfy" $ do+    it "succeeds if value does not satisfy predicate" $ do+      "bar" `shouldNotSatisfy` null++    it "fails if the value does satisfy predicate" $ do+      ("" `shouldNotSatisfy` null) `shouldThrow` expectationFailed (Reason "predicate succeeded on: \"\"")++  describe "shouldNotReturn" $ do+    it "succeeds if arguments does not represent equal values" $ do+      return "foo" `shouldNotReturn` "bar"++    it "fails if arguments do represent equal values" $ do+      (return "foo" `shouldNotReturn` "foo") `shouldThrow` expectationFailed (Reason "not expected: \"foo\"")++  describe "shouldNotContain" $ do+    it "succeeds if second argument is not contained in the first" $ do+      "I'm an hello world message" `shouldNotContain` "test"++    it "fails if first argument does contain the second" $ do+      ("foo abc def" `shouldNotContain` "def") `shouldThrow` expectationFailed (Reason "\"foo abc def\" does contain \"def\"")++  describe "shouldThrow" $ do+    it "can be used to require a specific exception" $ do+      throwIO DivideByZero `shouldThrow` (== DivideByZero)++    it "can be used to require any exception" $ do+      error "foobar" `shouldThrow` anyException++    it "can be used to require an exception of a specific type" $ do+      error "foobar" `shouldThrow` anyErrorCall++    it "can be used to require a specific exception" $ do+      error "foobar" `shouldThrow` errorCall "foobar"++    it "fails, if a required specific exception is not thrown" $ do+      (throwIO Overflow `shouldThrow` (== DivideByZero)) `shouldThrow` expectationFailed (Reason "predicate failed on expected exception: ArithException\narithmetic overflow")++    it "fails, if any exception is required, but no exception is thrown" $ do+      (return () `shouldThrow` anyException) `shouldThrow` expectationFailed (Reason "did not get expected exception: SomeException")++    it "fails, if an exception of a specific type is required, but no exception is thrown" $ do+      (return () `shouldThrow` anyErrorCall) `shouldThrow` expectationFailed (Reason "did not get expected exception: ErrorCall")