测试用例assertException

时间:2015-10-21 15:58:23

标签: haskell

我正在尝试测试函数是否抛出某个异常 我发现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

1 个答案:

答案 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 ]

四个测试用例是:

  1. 抛出DivideByZero异常 - 测试应该通过
  2. 没有抛出异常 - 测试失败
  3. 抛出错误的异常(不同类型) - 测试失败
  4. 抛出错误的异常(相同类型) - 测试失败
  5. 请注意,对于与目标异常类型不同的异常,您必须使用不同的catch处理程序。

    此外,我重新抛出任何AsyncException,因为这是HUnit在performTestCase (link)中所做的事情 例如,按Control-C将导致AsyncException。

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