{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Test.Tasty.Lua
(
pushModule
, testLuaFile
, translateResultsFromFile
, pathFailure
)
where
import Control.Exception (SomeException, try)
import Data.List (intercalate)
import Data.Semigroup (Semigroup (..))
import Foreign.Lua (Lua)
import Test.Tasty (TestName, TestTree)
import Test.Tasty.Providers (IsTest (..), singleTest, testFailed, testPassed)
import Test.Tasty.Lua.Module (pushModule)
import Test.Tasty.Lua.Core (Outcome (..), ResultTree (..), UnnamedTree (..),
runTastyFile)
import Test.Tasty.Lua.Translate (pathFailure, translateResultsFromFile)
testLuaFile :: (forall a . Lua a -> IO a)
-> TestName
-> FilePath
-> TestTree
testLuaFile runLua name fp =
let testAction = TestCase $ do
eitherResult <- runLua (runTastyFile fp)
return $ case eitherResult of
Left errMsg -> FailureSummary [([name], errMsg)]
Right result -> summarize result
in singleTest name testAction
newtype TestCase = TestCase (IO ResultSummary)
instance IsTest TestCase where
run _ (TestCase action) _ = do
result <- try action
return $ case result of
Left e -> testFailed (show (e :: SomeException))
Right summary -> case summary of
SuccessSummary n ->
testPassed $ "+++ Success: " ++ show n ++ " Lua tests passed"
FailureSummary fails ->
testFailed $ concatMap stringifyFailureGist fails
testOptions = return []
summarize :: [ResultTree] -> ResultSummary
summarize = foldr ((<>) . collectSummary) (SuccessSummary 0)
type LuaErrorMessage = String
type FailureInfo = ([TestName], LuaErrorMessage)
data ResultSummary
= SuccessSummary Int
| FailureSummary [FailureInfo]
stringifyFailureGist :: FailureInfo -> String
stringifyFailureGist (names, msg) =
intercalate " // " names ++ ":\n" ++ msg ++ "\n\n"
collectSummary :: ResultTree -> ResultSummary
collectSummary (ResultTree name tree) =
case tree of
SingleTest Success -> SuccessSummary 1
SingleTest (Failure msg) -> FailureSummary [([name], msg)]
TestGroup subtree -> foldr go (SuccessSummary 0) subtree
where go r summary = collectSummary r <> addGroup name summary
addGroup :: TestName -> ResultSummary -> ResultSummary
addGroup name (FailureSummary fs) = FailureSummary (map addName fs)
where addName (names, msg) = (name : names, msg)
addGroup _name summary = summary
instance Semigroup ResultSummary where
(SuccessSummary n) <> (SuccessSummary m) = SuccessSummary (n + m)
(SuccessSummary _) <> (FailureSummary fs) = FailureSummary fs
(FailureSummary fs) <> (SuccessSummary _) = FailureSummary fs
(FailureSummary fs) <> (FailureSummary gs) = FailureSummary (fs ++ gs)