简单的haskell单元测试

Dan*_*tep 52 haskell unit-testing

我想通过99个Haskell问题,我想专注于解决方案,但需要测试.如果我将第一个问题的解决方案作为3行.hs文件,

myLast :: [a] -> a
myLast [x] = x
myLast (_:xs) = myLast xs
Run Code Online (Sandbox Code Playgroud)

我可以添加的最小代码量是多少,以便我可以在线添加测试并运行它们runhaskell

Ed'*_*'ka 66

快速检查(你这basicaly生成测试输入)可能是测试纯函数的最佳方式.如果有问题的函数具有标准库中的模拟,您可以使用标准函数作为模型来测试函数:

{-# LANGUAGE TemplateHaskell #-}

import Test.QuickCheck
import Test.QuickCheck.All

myLast :: [a] -> a
myLast [x] = x
myLast (_:xs) = myLast xs

-- here we specify that 'myLast' should return exactly the same result
-- as 'last' for any given 'xs'
prop_myLast xs = myLast xs == last xs


return [] -- need this for GHC 7.8
-- quickCheckAll generates test cases for all 'prop_*' properties
main = $(quickCheckAll)
Run Code Online (Sandbox Code Playgroud)

如果你运行它,你会得到:

=== prop_myLast on tmp3.hs:12 ===
*** Failed! Exception: 'tmp3.hs:(7,1)-(8,25): Non-exhaustive patterns in function myLast' (after 1 test):  
[]
False
Run Code Online (Sandbox Code Playgroud)

因为你myLast没有处理[]大小写(它应该但应该抛出像'last'这样的错误).但是在这里我们可以简单地调整我们的测试,但是指定只应该使用非空字符串(使用==>组合器):

prop_myLast xs = length xs > 0 ==> myLast xs == last xs
Run Code Online (Sandbox Code Playgroud)

这使得所有100个自动生成的测试用例都可以通过myLast:

=== prop_myLast on tmp3.hs:11 ===
+++ OK, passed 100 tests.
True
Run Code Online (Sandbox Code Playgroud)

PS另一种指定myLast行为的方法可能是:

prop_myLast2 x xs = myLast (xs++[x]) == x
Run Code Online (Sandbox Code Playgroud)

或更好:

prop_myLast3 x xs = x `notElem` xs ==> myLast (xs++[x]) == x
Run Code Online (Sandbox Code Playgroud)

  • 根据我的例子,尝试添加`{ - #LANGUAGE TemplateHaskell# - }`.如果你的`runhaskell`指向`runghc`这应该可以解决问题.还将`prop_last'重命名为'prop_last` - 否则QuickCheck似乎忽略它. (2认同)
  • 所以一切正常(谢谢!),但现在我如何快速检查错误?我添加了`last'[] =错误"空列表"` (2认同)