hspec-expectations 0.3.3 → 0.8.4
raw patch · 11 files changed
Files
- LICENSE +1/−1
- README.lhs +0/−111
- hspec-expectations.cabal +40/−35
- src/Test/Hspec/Expectations.hs +105/−23
- src/Test/Hspec/Expectations/Contrib.hs +43/−5
- src/Test/Hspec/Expectations/Matcher.hs +26/−0
- test/Helper.hs +19/−0
- test/Spec.hs +14/−1
- test/Test/Hspec/Expectations/ContribSpec.hs +30/−0
- test/Test/Hspec/Expectations/MatcherSpec.hs +34/−0
- test/Test/Hspec/ExpectationsSpec.hs +105/−0
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,111 +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.3.3+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,9 +11,17 @@ , expectationFailure , shouldBe , shouldSatisfy+, shouldStartWith+, shouldEndWith , shouldContain+, shouldMatchList , shouldReturn +, shouldNotBe+, shouldNotSatisfy+, shouldNotContain+, shouldNotReturn+ -- * Expecting exceptions , shouldThrow @@ -34,48 +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 Prelude-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`, `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 the second.-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+-- wholly and intact, anywhere in @list@.+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 :: (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)@@ -84,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@@ -92,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@@ -108,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,22 +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 (-- module Test.Hspec.Expectations- -- * Predicates -- | (useful in combination with `shouldSatisfy`)-, isLeft+ isLeft , isRight++-- * Annotating expectations+, annotate ) where -import Test.Hspec.Expectations+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+#endif++-- |+-- 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+ 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")