[英]Testing haskell functions that return errors
Hi I have a similar to the following haskell function 嗨,我有一个类似于以下的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
I have a testing scheme to test bad inputs to make sure they return the correct error 我有一个测试方案来测试错误的输入,以确保它们返回正确的错误
tc1 = test 1
tc2 = test 2
tc3 = test 11
tc4 = test 77
allTests = [tc1, tc2, tc3, tc4]
But the problem is that when I run allTests
in ghci, I only get the first error. 但是问题是,当我在ghci中运行
allTests
时,我只会得到第一个错误。 I would like to have a list of all the errors 我想列出所有错误
How can this be done or some way I can catch the errors? 如何做到这一点或以某种方式可以捕获错误?
You could try to use catch
from Control.Exception
, but that's still an awkward way to achieve the goal. 您可以尝试使用
Control.Exception
catch
,但这仍然是实现目标的尴尬方式。
It'd be better to use a pure data type to capture errors, as they're easier to compose and collect. 最好使用纯数据类型来捕获错误,因为它们更易于编写和收集。 Normally, you'd use
Either
for that, but in this particular case, the success case would carry no information, so the type would be Either String ()
, which is isomorphic to Maybe String
. 通常,您将为此使用
Either
,但是在此特定情况下,成功情况将不包含任何信息,因此类型将为Either String ()
,与Maybe String
同构。 Rewriting test
to return Maybe String
is trivial: 重写
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
I added a tc5
value in order to demonstrate what happens when a test succeeds. 我添加了一个
tc5
值以演示测试成功时会发生什么。
You can evaluate all of those test cases, but if you want only the failure cases, you can use catMaybes
from Data.Maybe
: 您可以评估所有这些测试用例,但如果仅需要失败用例,则可以使用
catMaybes
的Data.Maybe
:
allTests = catMaybes [tc1, tc2, tc3, tc4, tc5]
Here's the result of running allTests
: 这是运行
allTests
的结果:
*Q46376632> allTests
["shouldnt have been 1",
"shouldnt have been 2",
"shouldnt have been 11",
"shouldnt have been 77"]
If you can't change the function you're testing, you can try something like the following, but it's hardly elegant: 如果您无法更改要测试的功能,则可以尝试以下操作,但操作起来不太优雅:
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]
When running it, you get output like this: 运行它时,您将获得如下输出:
*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
At this point, you'd probably be better of using a proper testing framework. 此时,最好使用适当的测试框架。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.