-->

如何测试在Haskell错误?(How do I test for an error in Hask

2019-07-03 18:43发布

我希望能够确保一种功能,当它接收和无效的值都将抛出一个错误。 例如,让说,我有一个函数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

[我的解决方案]

这是我结束了基于@哈马尔的评论去。

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

Answer 1:

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

我加了msg参数assertError匹配如何assertRaises工作,并列入选择性进口这么喜欢我菜鸟可以学习,其中常用的东西都来自进口。

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


Answer 2:

有几种方法在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

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



文章来源: How do I test for an error in Haskell?