我如何测试Haskell中的错误?

我希望能够确保函数在接收到无效值时会抛出错误。 例如,让我说我有一个函数pos只返回一个正数:

pos :: Int -> Int
pos x
   | x >= 0 = x
   | otherwise = error "Invalid Input"

这是一个简单的例子,但我希望你明白。

我希望能够编写一个预期会出现错误并将其视为合格测试的测试用例。 例如:

tests = [pos 1 == 1, assertError pos (-1), pos 2 == 2, assertError pos (-2)]
runTests = all (== True) tests

[我的解决方案]

基于@ hammar的评论,我最终选择了这一点。

instance Eq ErrorCall where
    x == y = (show x) == (show y)

assertException :: (Exception e, Eq e) => e -> IO a -> IO ()
assertException ex action =
    handleJust isWanted (const $ return ()) $ do
        action
        assertFailure $ "Expected exception: " ++ show ex
  where isWanted = guard . (== ex) 

assertError ex f = 
    TestCase $ assertException (ErrorCall ex) $ evaluate f

tests = TestList [ (pos 0) ~?= 0
                 , (pos 1) ~?= 1
                 , assertError "Invalid Input" (pos (-1))
                 ]   

main = runTestTT tests

OP的解决方案定义了assertException ,但它看起来像testpack中的Test.HUnit.Tools.assertRaises在这里也是可用的。

我为assertError添加了msg参数以匹配assertRaises工作方式,并且包含了选择性导入,因此像我这样的noob可以了解常用的东西从哪里导入。

import Control.Exception (ErrorCall(ErrorCall), evaluate)
import Test.HUnit.Base  ((~?=), Test(TestCase, TestList))
import Test.HUnit.Text (runTestTT)
import Test.HUnit.Tools (assertRaises)

pos :: Int -> Int
pos x
   | x >= 0 = x
   | otherwise = error "Invalid Input"

instance Eq ErrorCall where
    x == y = (show x) == (show y)

assertError msg ex f = 
    TestCase $ assertRaises msg (ErrorCall ex) $ evaluate f

tests = TestList [
  (pos 0) ~?= 0
  , (pos 1) ~?= 1
  , assertError "Negative argument raises an error" "Invalid Input" (pos (-1))
  ]   

main = runTestTT tests

有几种方法可以处理Haskell中的错误。 这里是一个概述:http://www.randomhacks.net/articles/2007/03/10/haskell-8-ways-to-report-errors

[编辑]

第一个例子显示如何捕捉错误,例如

half :: Int -> Int 
half x = if even x then x `div` 2 else error "odd"

main = do catch (print $ half 23) (err -> print err)

也就是说,这种错误处理更适合IO东西,像你这样的纯代码也许,任何一种或类似的东西通常都是更好的选择。 它可以像...一样简单

pos :: Int -> Maybe Int
pos x
   | x >= 0 = Just x
   | otherwise = Nothing

tests = [pos 1 == Just 1
        ,pos (-1) == Nothing
        ,pos 2 == Just 2
        ,pos (-2) == Nothing
        ]

main = print $ and tests

...如果你不需要错误类型。

链接地址: http://www.djcxy.com/p/11439.html

上一篇: How do I test for an error in Haskell?

下一篇: Selecting rows where a field is null using PHP PDO prepared statements and MySQL