我正在尝试测试函数是否抛出某个异常 我发现this回答女巫这样做了:
import Control.Exception
import Control.Monad
import Test.HUnit
assertException :: (Exception e, Eq e) => String -> e -> IO a -> IO ()
assertException preface expected action =
handleJust isWanted (const $ return ()) $ do
action
assertFailure msg
where
isWanted = guard . (== expected)
msg = preface ++ "\nexpected exception: " ++ show expected
testPasses = TestCase $ assertException "Test1" DivideByZero (evaluate $ 5 `div` 0)
testFails = TestCase $ assertException "Test2" DivideByZero (evaluate $ 5 `div` 1)
main = runTestTT $ TestList [ testPasses, testFails ]
女巫跑步时表示:
### Failure in: 1
Test2
expected exception: divide by zero
Cases: 2 Tried: 2 Errors: 0 Failures: 1
但是assertException
没有显示实际的异常,或者没有显示
有没有办法能够显示实际的例外或缺席?
我尝试使用catch
包装动作,但我不知道如何将实际异常传递给msg
。
答案 0 :(得分:2)
这是一种方法:
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Exception
import Control.Monad
import Test.HUnit
import GHC.Natural
assertException4 :: (Exception e, Eq e) => String -> e -> IO a -> IO ()
assertException4 preface expected action = do
r <- catches
(action >> return (Just "no exception thrown"))
[ Handler (\e -> return $ if e == expected
then Nothing
else Just ("wrong exception thrown, expected " ++ show expected ++ ", got: " ++ show e))
-- see the comments below about these two handlers:
, Handler (\e -> throw (e :: AsyncException))
, Handler (\(e::SomeException) -> return $ Just ("some other exception thrown: " ++ show e))
]
case r of
Nothing -> return ()
Just msg -> assertFailure (preface ++ ": " ++ msg)
test1 = TestCase $ assertException4 "Test1" DivideByZero (evaluate $ 5 `div` 0)
test2 = TestCase $ assertException4 "Test2" DivideByZero (evaluate $ 5 `div` 1)
test3 = TestCase $ assertException4 "Test3" DivideByZero (evaluate $ [1,2,3] !! 4)
test4 = TestCase $ assertException4 "Test4" DivideByZero (evaluate $ (fromInteger (0 - 3) :: Natural) )
main = runTestTT $ TestList [ test1, test2, test3, test4 ]
四个测试用例是:
请注意,对于与目标异常类型不同的异常,您必须使用不同的catch处理程序。
此外,我重新抛出任何AsyncException,因为这是HUnit在performTestCase
(link)中所做的事情
例如,按Control-C将导致AsyncException。
请注意,未捕获的异常将被HUnit报告为错误,并且将打印出异常。您可以通过删除AsyncException和SomeException的处理程序来测试它。