我希望能够确保一种功能,当它接收和无效的值都将抛出一个错误。 例如,让说,我有一个函数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
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
有几种方法在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
...如果你并不需要一个错误类型。