hspec-core-2.2.1: test/Test/Hspec/Core/FormattersSpec.hs
{-# LANGUAGE CPP #-}
module Test.Hspec.Core.FormattersSpec (main, spec) where
import Prelude ()
import Helper
import qualified Test.Hspec.Core.Spec as H
import qualified Test.Hspec.Core.Runner as H
import qualified Test.Hspec.Core.Formatters as H
#ifndef mingw32_HOST_OS
import System.Console.ANSI
#endif
main :: IO ()
main = hspec spec
testSpec :: H.Spec
testSpec = do
H.describe "Example" $ do
H.it "success" (H.Success)
H.it "fail 1" (H.Fail Nothing "fail message")
H.it "pending" (H.pendingWith "pending message")
H.it "fail 2" (H.Fail Nothing "")
H.it "exceptions" (undefined :: H.Result)
H.it "fail 3" (H.Fail Nothing "")
spec :: Spec
spec = do
describe "silent" $ do
let runSpec = fmap fst . capture . H.hspecWithResult H.defaultConfig {H.configFormatter = Just H.silent}
it "produces no output" $ do
runSpec testSpec `shouldReturn` ""
describe "failed_examples" $ do
failed_examplesSpec H.failed_examples
describe "progress" $ do
let runSpec = captureLines . H.hspecWithResult H.defaultConfig {H.configFormatter = Just H.progress}
it "produces '..F...FF.F' style output" $ do
r <- runSpec testSpec
head r `shouldBe` ".F.FFF"
context "same as failed_examples" $ do
failed_examplesSpec H.progress
describe "specdoc" $ do
let runSpec = captureLines . H.hspecWithResult H.defaultConfig {H.configFormatter = Just H.specdoc}
it "displays a header for each thing being described" $ do
_:x:_ <- runSpec testSpec
x `shouldBe` "Example"
it "displays one row for each behavior" $ do
r <- runSpec $ do
H.describe "List as a Monoid" $ do
H.describe "mappend" $ do
H.it "is associative" True
H.describe "mempty" $ do
H.it "is a left identity" True
H.it "is a right identity" True
H.describe "Maybe as a Monoid" $ do
H.describe "mappend" $ do
H.it "is associative" True
H.describe "mempty" $ do
H.it "is a left identity" True
H.it "is a right identity" True
normalizeSummary r `shouldBe` [
""
, "List as a Monoid"
, " mappend"
, " is associative"
, " mempty"
, " is a left identity"
, " is a right identity"
, "Maybe as a Monoid"
, " mappend"
, " is associative"
, " mempty"
, " is a left identity"
, " is a right identity"
, ""
, "Finished in 0.0000 seconds"
, "6 examples, 0 failures"
]
it "outputs an empty line at the beginning (even for non-nested specs)" $ do
r <- runSpec $ do
H.it "example 1" True
H.it "example 2" True
normalizeSummary r `shouldBe` [
""
, "example 1"
, "example 2"
, ""
, "Finished in 0.0000 seconds"
, "2 examples, 0 failures"
]
it "displays a row for each successfull, failed, or pending example" $ do
r <- runSpec testSpec
r `shouldSatisfy` any (== " fail 1 FAILED [1]")
r `shouldSatisfy` any (== " success")
it "displays a '#' with an additional message for pending examples" $ do
r <- runSpec testSpec
r `shouldSatisfy` any (== " # PENDING: pending message")
context "with an empty group" $ do
it "omits that group from the report" $ do
r <- runSpec $ do
H.describe "foo" $ do
H.it "example 1" True
H.describe "bar" $ do
return ()
H.describe "baz" $ do
H.it "example 2" True
normalizeSummary r `shouldBe` [
""
, "foo"
, " example 1"
, "baz"
, " example 2"
, ""
, "Finished in 0.0000 seconds"
, "2 examples, 0 failures"
]
context "same as failed_examples" $ do
failed_examplesSpec H.progress
failed_examplesSpec :: H.Formatter -> Spec
failed_examplesSpec formatter = do
let runSpec = captureLines . H.hspecWithResult H.defaultConfig {H.configFormatter = Just formatter}
it "summarizes the time it takes to finish" $ do
r <- runSpec (return ())
normalizeSummary r `shouldSatisfy` any (== "Finished in 0.0000 seconds")
context "displays a detailed list of failures" $ do
it "prints all requirements that are not met" $ do
r <- runSpec testSpec
r `shouldSatisfy` any (== " 1) Example fail 1")
it "prints the exception type for requirements that fail due to an uncaught exception" $ do
r <- runSpec $ do
H.it "foobar" (undefined :: Bool)
r `shouldContain` [
" 1) foobar"
, " uncaught exception: ErrorCall (Prelude.undefined)"
]
it "prints all descriptions when a nested requirement fails" $ do
r <- runSpec $
H.describe "foo" $ do
H.describe "bar" $ do
H.it "baz" False
r `shouldSatisfy` any (== " 1) foo.bar baz")
context "when a failed example has a source location" $ do
let bestEffortExplanation = "Source locations marked with \"best-effort\" are calculated heuristically and may be incorrect."
it "includes the source locations above the error messages" $ do
let loc = H.Location "test/FooSpec.hs" 23 0 H.ExactLocation
addLoc e = e {H.itemLocation = Just loc}
r <- runSpec $ H.mapSpecItem_ addLoc $ do
H.it "foo" False
r `shouldContain` [" test/FooSpec.hs:23: ", " 1) foo"]
context "when source location is exact" $ do
it "includes that source locations" $ do
let loc = H.Location "test/FooSpec.hs" 23 0 H.ExactLocation
addLoc e = e {H.itemLocation = Just loc}
r <- runSpec $ H.mapSpecItem_ addLoc $ do
H.it "foo" False
r `shouldSatisfy` any (== " test/FooSpec.hs:23: ")
it "does not include 'best-effort' explanation" $ do
let loc = H.Location "test/FooSpec.hs" 23 0 H.ExactLocation
addLoc e = e {H.itemLocation = Just loc}
r <- runSpec $ H.mapSpecItem_ addLoc $ do
H.it "foo" False
r `shouldSatisfy` all (/= bestEffortExplanation)
context "when source location is best-effort" $ do
it "marks that source location as 'best-effort'" $ do
let loc = H.Location "test/FooSpec.hs" 23 0 H.BestEffort
addLoc e = e {H.itemLocation = Just loc}
r <- runSpec $ H.mapSpecItem_ addLoc $ do
H.it "foo" False
r `shouldSatisfy` any (== " test/FooSpec.hs:23: (best-effort)")
it "includes 'best-effort' explanation" $ do
let loc = H.Location "test/FooSpec.hs" 23 0 H.BestEffort
addLoc e = e {H.itemLocation = Just loc}
r <- runSpec $ H.mapSpecItem_ addLoc $ do
H.it "foo" False
r `shouldSatisfy` any (== bestEffortExplanation)
it "summarizes the number of examples and failures" $ do
r <- runSpec testSpec
r `shouldSatisfy` any (== "6 examples, 4 failures, 1 pending")
-- Windows has no support for ANSI escape codes. The Console API is used for
-- colorized output, hence the following tests do not work on Windows.
#ifndef mingw32_HOST_OS
it "shows summary in green if there are no failures" $ do
r <- captureLines $ H.hspecWithResult H.defaultConfig {H.configColorMode = H.ColorAlways} $ do
H.it "foobar" True
r `shouldSatisfy` any (== (green ++ "1 example, 0 failures" ++ reset))
it "shows summary in yellow if there are pending examples" $ do
r <- captureLines $ H.hspecWithResult H.defaultConfig {H.configColorMode = H.ColorAlways} $ do
H.it "foobar" H.pending
r `shouldSatisfy` any (== (yellow ++ "1 example, 0 failures, 1 pending" ++ reset))
it "shows summary in red if there are failures" $ do
r <- captureLines $ H.hspecWithResult H.defaultConfig {H.configColorMode = H.ColorAlways} $ do
H.it "foobar" False
r `shouldSatisfy` any (== (red ++ "1 example, 1 failure" ++ reset))
it "shows summary in red if there are both failures and pending examples" $ do
r <- captureLines $ H.hspecWithResult H.defaultConfig {H.configColorMode = H.ColorAlways} $ do
H.it "foo" False
H.it "bar" H.pending
r `shouldSatisfy` any (== (red ++ "2 examples, 1 failure, 1 pending" ++ reset))
where
green = setSGRCode [SetColor Foreground Dull Green]
yellow = setSGRCode [SetColor Foreground Dull Yellow]
red = setSGRCode [SetColor Foreground Dull Red]
reset = setSGRCode [Reset]
#endif