简体   繁体   English

测试返回错误的haskell函数

[英]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 : 您可以评估所有这些测试用例,但如果仅需要失败用例,则可以使用catMaybesData.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM