测试用例assertException

爱奥努特

我正在尝试测试一个函数是否抛出某个异常。
我发现这个答案女巫是这样做的:

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

埃里克

这是一种实现方法:

{-# 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 ]

四个测试用例是:

  1. 引发DivideByZero异常-测试应该通过
  2. 没有引发异常-测试应该失败
  3. 抛出错误的异常(不同类型)-测试应该失败
  4. 抛出错误的异常(相同类型)-测试应该失败

请注意,对于与目标异常类型不同的异常,您必须具有不同的catch处理程序。

另外,我重新抛出任何AsyncException,因为例如HUnit在performTestCase (链接)命中Control-C时将执行此操作,将导致AsyncException。

请注意,未捕获的异常将由HUnit报告为“错误”,并且该异常将被打印出来。您可以通过删除AsyncException和SomeException的处理程序进行测试。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章