基于stackoverflow上的问题13350164 如何在Haskell中测试错误?,我试图编写一个单元测试来断言如果给定无效输入,递归函数会引发异常。我采用的方法对于非递归函数(或者第一次调用引发异常时)效果很好,但是一旦异常在调用链深处发生,断言就会失败。
我已经阅读了问题6537766 Haskell处理错误的方法 的优秀答案,但不幸的是,该建议对于我当前的学习曲线来说有点太泛泛了。我的猜测是这里的问题与惰性求值和非纯测试代码有关,但我希望能得到专家的解释。
在这种情况下,我应该采用不同的错误处理方法(例如
以下是我想出的代码。前两个测试用例成功了,但第三个测试用例失败并显示
我已经阅读了问题6537766 Haskell处理错误的方法 的优秀答案,但不幸的是,该建议对于我当前的学习曲线来说有点太泛泛了。我的猜测是这里的问题与惰性求值和非纯测试代码有关,但我希望能得到专家的解释。
在这种情况下,我应该采用不同的错误处理方法(例如
Maybe
或Either
),还是有合理的修复方法可以使测试用例在使用此风格时正确工作?以下是我想出的代码。前两个测试用例成功了,但第三个测试用例失败并显示
"Received no exception, but was expecting exception: Negative item"
。import Control.Exception (ErrorCall(ErrorCall), evaluate)
import Test.HUnit.Base ((~?=), Test(TestCase, TestList))
import Test.HUnit.Text (runTestTT)
import Test.HUnit.Tools (assertRaises)
sumPositiveInts :: [Int] -> Int
sumPositiveInts [] = error "Empty list"
sumPositiveInts (x:[]) = x
sumPositiveInts (x:xs) | x >= 0 = x + sumPositiveInts xs
| otherwise = error "Negative item"
instance Eq ErrorCall where
x == y = (show x) == (show y)
assertError msg ex f =
TestCase $ assertRaises msg (ErrorCall ex) $ evaluate f
tests = TestList [
assertError "Empty" "Empty list" (sumPositiveInts ([]))
, assertError "Negative head" "Negative item" (sumPositiveInts ([-1, -1]))
, assertError "Negative second item" "Negative item" (sumPositiveInts ([1, -1]))
]
main = runTestTT tests
Maybe
是一个MonadPlus
!在我看来,更清晰的写法是sumPositives xs = do { guard $ not (null xs) ; guard $ all (>0) xs ; return (sum xs) }
。 - dave4420