module Test.Hspec.Core where
import System.IO.Silently
import Control.Exception
data Result = Success | Pending String | Fail String
deriving Eq
type UnevaluatedSpec = Spec AnyExample
type EvaluatedSpec = Spec Result
data Spec a = SpecGroup String [Spec a]
| SpecExample String a
describe :: String -> [Spec a] -> Spec a
describe = SpecGroup
descriptions :: [Spec a] -> [Spec a]
descriptions = id
safeEvaluateExample :: AnyExample -> IO Result
safeEvaluateExample example' = do
evaluateExample example' `catches` [
Handler (\e -> throw (e :: AsyncException)),
Handler (\e -> return $ Fail (show (e :: SomeException)))
]
it :: Example a => String -> a -> UnevaluatedSpec
it requirement' example' = SpecExample requirement' (AnyExample example')
class Example a where
evaluateExample :: a -> IO Result
instance Example Bool where
evaluateExample bool = evaluateExample $ if bool then Success else Fail ""
instance Example Result where
evaluateExample result' = silence $ result' `seq` return result'
data AnyExample = forall a. Example a => AnyExample a
instance Example AnyExample where
evaluateExample (AnyExample a) = evaluateExample a
pending :: String
-> Result
pending = Pending
failedCount :: [EvaluatedSpec] -> Int
failedCount = sum . map count
where
count (SpecGroup _ xs) = sum (map count xs)
count (SpecExample _ x) = if isFailure x then 1 else 0
failure :: [EvaluatedSpec] -> Bool
failure = any p
where
p (SpecGroup _ xs) = any p xs
p (SpecExample _ x) = isFailure x
success :: [EvaluatedSpec] -> Bool
success = not . failure
isFailure :: Result -> Bool
isFailure (Fail _) = True
isFailure _ = False
quantify :: (Show a, Num a, Eq a) => a -> String -> String
quantify 1 s = "1 " ++ s
quantify n s = show n ++ " " ++ s ++ "s"