您好我有类似以下的haskell功能
test :: Int -> Bool
test 1 = error "shouldnt have been 1"
test 2 = error "shouldnt have been 2"
test 11 = error "shouldnt have been 11"
test 77 = error "shouldnt have been 77"
test _ = True
我有一个测试方案来测试错误的输入,以确保它们返回正确的错误
tc1 = test 1
tc2 = test 2
tc3 = test 11
tc4 = test 77
allTests = [tc1, tc2, tc3, tc4]
但问题是当我在ghci中运行allTests
时,我只得到第一个错误。我想列出所有错误
如何做到这一点或以某种方式我能抓住错误?
答案 0 :(得分:4)
您可以尝试使用catch
中的Control.Exception
,但这仍然是实现目标的尴尬方式。
使用纯数据类型来捕获错误会更好,因为它们更容易编写和收集。通常情况下,您可以使用Either
,但在此特定情况下,成功案例不会包含任何信息,因此类型为Either String ()
,与Maybe String
同构。重写test
以返回Maybe String
是微不足道的:
test :: Int -> Maybe String
test 1 = Just "shouldnt have been 1"
test 2 = Just "shouldnt have been 2"
test 11 = Just "shouldnt have been 11"
test 77 = Just "shouldnt have been 77"
test _ = Nothing
tc1 = test 1
tc2 = test 2
tc3 = test 11
tc4 = test 77
tc5 = test 5
我添加了tc5
值,以证明测试成功后会发生什么。
您可以评估所有这些测试用例,但如果您只想要失败案例,则可以使用catMaybes
中的Data.Maybe
:
allTests = catMaybes [tc1, tc2, tc3, tc4, tc5]
这是运行allTests
:
*Q46376632> allTests
["shouldnt have been 1",
"shouldnt have been 2",
"shouldnt have been 11",
"shouldnt have been 77"]
如果您无法更改正在测试的功能,您可以尝试以下类似的功能,但它并不优雅:
tc1 = catch (print $ test 1) (\err -> print (err :: SomeException))
tc2 = catch (print $ test 2) (\err -> print (err :: SomeException))
tc3 = catch (print $ test 11) (\err -> print (err :: SomeException))
tc4 = catch (print $ test 77) (\err -> print (err :: SomeException))
tc5 = catch (print $ test 5) (\err -> print (err :: SomeException))
allTests = sequence_ [tc1, tc2, tc3, tc4, tc5]
运行时,你得到如下输出:
*Q46376632> allTests
shouldnt have been 1
CallStack (from HasCallStack):
error, called at 46376632.hs:14:10 in main:Q46376632
shouldnt have been 2
CallStack (from HasCallStack):
error, called at 46376632.hs:15:10 in main:Q46376632
shouldnt have been 11
CallStack (from HasCallStack):
error, called at 46376632.hs:16:11 in main:Q46376632
shouldnt have been 77
CallStack (from HasCallStack):
error, called at 46376632.hs:17:11 in main:Q46376632
True
此时,您可能更擅长使用适当的测试框架。