-- | This module contains the runners that take a set of specs, evaluate their examples, and -- report to a given handle. -- module Test.Hspec.Runner ( Specs, hspec, hspecX, hspecB, hHspec, hHspecWithFormat, describe, it, toExitCode ) where import Test.Hspec.Core import Test.Hspec.Formatters import System.IO import System.CPUTime (getCPUTime) import Control.Monad (when) import System.Exit import Control.Exception (bracket_) type Specs = [Spec] -- | Evaluate and print the result of checking the spec examples. runFormatter :: Formatter -> Handle -> String -> [String] -> Specs -> IO Specs runFormatter formatter h _ errors [] = do errorsFormatter formatter h (reverse errors) return [] runFormatter formatter h group errors (iospec:ioss) = do spec <- evaluateSpec iospec when (group /= name spec) (exampleGroupStarted formatter h spec) case result spec of (Success ) -> examplePassed formatter h spec errors (Fail _ ) -> exampleFailed formatter h spec errors (Pending _) -> examplePending formatter h spec errors let errors' = if isFailure (result spec) then errorDetails spec (length errors) : errors else errors specs <- runFormatter formatter h (name spec) errors' ioss return $ spec : specs errorDetails :: Spec -> Int -> String errorDetails spec i = case result spec of (Fail s ) -> concat [ show (i + 1), ") ", name spec, " ", requirement spec, " FAILED", if null s then "" else "\n" ++ s ] _ -> "" -- | Use in place of @hspec@ to also exit the program with an @ExitCode@ hspecX :: Specs -> IO a hspecX ss = hspecB ss >>= exitWith . toExitCode -- | Use in place of hspec to also give a @Bool@ success indication hspecB :: Specs -> IO Bool hspecB ss = hspec ss >>= return . success -- | Create a document of the given specs and write it to stdout. hspec :: Specs -> IO [Spec] hspec ss = hHspec stdout ss -- | Create a document of the given specs and write it to the given handle. -- -- > writeReport filename specs = withFile filename WriteMode (\ h -> hHspec h specs) -- hHspec :: Handle -> Specs -> IO Specs hHspec h = hHspecWithFormat (specdoc $ h == stdout) h -- | Create a document of the given specs and write it to the given handle. -- THIS IS LIKELY TO CHANGE hHspecWithFormat :: Formatter -> Handle -> Specs -> IO Specs hHspecWithFormat formatter h ss = bracket_ (when (usesFormatting formatter) $ restoreFormat h) (when (usesFormatting formatter) $ restoreFormat h) (do t0 <- getCPUTime specList <- runFormatter formatter h "" [] ss t1 <- getCPUTime let runTime = ((fromIntegral $ t1 - t0) / (10.0^(12::Integer)) :: Double) (footerFormatter formatter) h specList runTime return specList) toExitCode :: Bool -> ExitCode toExitCode True = ExitSuccess toExitCode False = ExitFailure 1