HUnit-Plus-2.0.0: test/Tests/Test/HUnitPlus/ReporterUtils.hs
{-# LANGUAGE OverloadedStrings #-}
module Tests.Test.HUnitPlus.ReporterUtils where
import Control.Monad
import Data.List
import Distribution.TestSuite(Result(Pass, Fail))
import Test.HUnitPlus.Reporting
import qualified Data.HashMap.Strict as HashMap
import qualified Data.Text as Strict
data ReportEvent =
End Double
| StartSuite
| EndSuite Double
| StartCase
| EndCase Double
| Skip
| Progress Strict.Text
| Failure Strict.Text
| Error Strict.Text
| Exception Strict.Text
| SystemErr Strict.Text
| SystemOut Strict.Text
deriving (Show)
instance Eq ReportEvent where
End e1 == End e2 = e1 == e2
StartSuite == StartSuite = True
EndSuite e1 == EndSuite e2 = e1 == e2
StartCase == StartCase = True
EndCase e1 == EndCase e2 = e1 == e2
Skip == Skip = True
Progress s1 == Progress s2 = s1 == s2
Failure s1 == Failure s2 = s1 == s2
Error s1 == Error s2 = s1 == s2
Exception s1 == Error s2 = Strict.isInfixOf s1 s2
Error s1 == Exception s2 = Strict.isInfixOf s2 s1
Exception s1 == Exception s2 = s1 == s2
SystemErr s1 == SystemErr s2 = s1 == s2
SystemOut s1 == SystemOut s2 = s1 == s2
_ == _ = False
type ReporterOp us = (State, us) -> IO (State, us)
loggingReporter :: Reporter [ReportEvent]
loggingReporter = defaultReporter {
reporterStart = return [],
reporterEnd = (\time _ events -> return (events ++ [End time])),
reporterStartSuite = (\_ events -> return (events ++ [StartSuite])),
reporterEndSuite = (\time _ events -> return (events ++ [EndSuite time])),
reporterStartCase = (\_ events -> return (events ++ [StartCase])),
reporterEndCase = (\time _ events -> return (events ++ [EndCase time])),
reporterSkipCase = (\_ events -> return (events ++ [Skip])),
reporterCaseProgress = (\msg _ events -> return (events ++ [Progress msg])),
reporterFailure = (\msg _ events -> return (events ++ [Failure msg])),
reporterError = (\msg _ events -> return (events ++ [Error msg])),
reporterSystemErr = (\msg _ events -> return (events ++ [SystemErr msg])),
reporterSystemOut = (\msg _ events -> return (events ++ [SystemOut msg]))
}
initState :: State
initState = State { stName = "", stPath = [], stCounts = zeroCounts,
stOptions = HashMap.empty, stOptionDescs = [] }
setName :: Strict.Text -> ReporterOp us
setName name (s @ State { stName = _ }, repstate) =
return (s { stName = name }, repstate)
setOpt :: Strict.Text -> Strict.Text -> ReporterOp us
setOpt key value (s @ State { stOptions = opts }, repstate) =
return (s { stOptions = HashMap.insert key value opts }, repstate)
pushPath :: Strict.Text -> ReporterOp us
pushPath name (s @ State { stPath = path }, repstate) =
return (s { stPath = Label name : path }, repstate)
popPath :: ReporterOp us
popPath (s @ State { stPath = _ : path }, repstate) =
return (s { stPath = path }, repstate)
addOption :: Strict.Text -> Strict.Text -> ReporterOp us
addOption key value (s @ State { stOptions = opts }, repstate) =
return (s { stOptions = HashMap.insert key value opts }, repstate)
countAsserts :: Word -> ReporterOp us
countAsserts count (s @ State { stCounts = c @ Counts { cAsserts = n } },
repstate) =
return (s { stCounts = c { cAsserts = n + count,
cCaseAsserts = count } }, repstate)
countTried :: Word -> ReporterOp us
countTried count (s @ State { stCounts = c @ Counts { cCases = cases,
cTried = tried } },
repstate) =
return (s { stCounts = c { cCases = cases + count,
cTried = tried + count } },
repstate)
countSkipped :: Word -> ReporterOp us
countSkipped count (s @ State { stCounts = c @ Counts { cSkipped = skipped,
cCases = cases } },
repstate) =
return (s { stCounts = c { cSkipped = skipped + count,
cCases = cases + count } },
repstate)
countErrors :: Word -> ReporterOp us
countErrors count (s @ State { stCounts = c @ Counts { cErrors = errors } },
repstate) =
return (s { stCounts = c { cErrors = errors + count } }, repstate)
countFailed :: Word -> ReporterOp us
countFailed count (s @ State { stCounts = c @ Counts { cFailures = failed } },
repstate) =
return (s { stCounts = c { cFailures = failed + count } }, repstate)
reportProgress :: Reporter us -> Strict.Text -> ReporterOp us
reportProgress reporter msg (state, repstate) =
do
repstate' <- (reporterCaseProgress reporter) msg state repstate
return (state, repstate')
reportSystemErr :: Reporter us -> Strict.Text -> ReporterOp us
reportSystemErr reporter msg (state, repstate) =
do
repstate' <- (reporterSystemErr reporter) msg state repstate
return (state, repstate')
reportSystemOut :: Reporter us -> Strict.Text -> ReporterOp us
reportSystemOut reporter msg (state, repstate) =
do
repstate' <- (reporterSystemOut reporter) msg state repstate
return (state, repstate')
reportFailure :: Reporter us -> Strict.Text -> ReporterOp us
reportFailure reporter msg (state, repstate) =
do
repstate' <- (reporterFailure reporter) msg state repstate
return (state, repstate')
reportError :: Reporter us -> Strict.Text -> ReporterOp us
reportError reporter msg (state, repstate) =
do
repstate' <- (reporterError reporter) msg state repstate
return (state, repstate')
reportSkip :: Reporter us -> ReporterOp us
reportSkip reporter (state, repstate) =
do
repstate' <- (reporterSkipCase reporter) state repstate
return (state, repstate')
reportStartCase :: Reporter us -> ReporterOp us
reportStartCase reporter (state, repstate) =
do
repstate' <- (reporterStartCase reporter) state repstate
return (state, repstate')
reportEndCase :: Reporter us -> Double -> ReporterOp us
reportEndCase reporter time (state, repstate) =
do
repstate' <- (reporterEndCase reporter) time state repstate
return (state, repstate')
reportStartSuite :: Reporter us -> ReporterOp us
reportStartSuite reporter (state, repstate) =
do
repstate' <- (reporterStartSuite reporter) state repstate
return (state, repstate')
reportEndSuite :: Reporter us -> Double -> ReporterOp us
reportEndSuite reporter time (state, repstate) =
do
repstate' <- (reporterEndSuite reporter) time state repstate
return (state, repstate')
reportEnd :: Reporter us -> Double -> ReporterOp us
reportEnd reporter time (state @ State { stCounts = counts }, repstate) =
do
repstate' <- (reporterEnd reporter) time counts repstate
return (state, repstate')
runReporterTest :: Eq us => Reporter us -> [ReporterOp us] -> us ->
(us -> String) -> IO Result
runReporterTest reporter tests expected format =
do
initrepstate <- reporterStart reporter
(_, actual) <- foldM (\state op -> op state) (initState, initrepstate) tests
if actual == expected
then return Pass
else return (Fail ("Expected " ++ format expected ++
"\nbut got " ++ format actual))