我正在学习Haskell,并且是一名优秀的开发人员,在我去的时候编写单元测试。我实现了各种排序算法和相应的测试。但是,我觉得单独的测试是多余的,因为输入和输出不变,只有用于对输入进行排序的算法。有没有办法在各种其他单元测试框架中尽可能地创建数据驱动的测试或数据表?
module RecursionSpec (main, spec) where
import Test.Hspec
import Recursion
main :: IO ()
main = hspec spec
spec :: Spec
spec = do
let input = [3, 1, 5, 2, 4]
output = [1, 2, 3, 4, 5]
describe "bubblesort" $ do
it ("sorts " ++ show input) $ do
bubblesort input `shouldBe` output
describe "mergesort" $ do
it ("sorts " ++ show input) $ do
mergesort input `shouldBe` output
describe "quicksort" $ do
it ("sorts " ++ show input) $ do
quicksort input `shouldBe` output
另外,我收到以下警告,我想了解并消除。
warning: [-Wtype-defaults]
• Defaulting the following constraints to type ‘Integer’
(Show a0)
arising from a use of ‘show’ at test/RecursionSpec.hs:14:21-30
(Eq a0)
arising from a use of ‘shouldBe’ at test/RecursionSpec.hs:15:7-40
(Ord a0)
arising from a use of ‘bubblesort’ at test/RecursionSpec.hs:15:7-22
(Num a0)
arising from the literal ‘1’ at test/RecursionSpec.hs:12:17
(Num a0)
arising from the literal ‘3’ at test/RecursionSpec.hs:11:16
• In the second argument of ‘(++)’, namely ‘show input’
In the first argument of ‘it’, namely ‘("sorts " ++ show input)’
In the expression: it ("sorts " ++ show input)
答案 0 :(得分:3)
您可以定义更高阶的函数,如:
describeSort :: Ord a => String -> ([a] -> [a]) -> [a] -> [a] -> SpecWith b
describeSort sortName sorter input output =
describe sortName $ do
it ("sorts " ++ show input) $ do
sorter input `shouldBe` output
它不是数据驱动的,但在这种情况下它基本上删除了样板(我无法验证语法是否完全正确,不需要手持HSpec安装)。 / p>
然后您可以将测试定义为:
spec :: Spec
spec = do
let input = [3, 1, 5, 2, 4]
output = [1, 2, 3, 4, 5]
describeSort "bubblesort" bubblesort input output
describeSort "mergesort" mergeSort input output
describeSort "quicksort" quickSort input output
专门针对Haskell的更多数据驱动(属性测试)测试框架是QuickCheck
。它允许您定义"属性"遵循功能,然后可以生成数据来测试这些。例如,对排序函数的快速测试可以写成:
quickCheck (\xl -> bubblesort xl == sort xl)
其中sort
是Data.List
版本,bubblesort
是您正在测试的实施。然后,QuickCheck将生成100个符合约束的列表(必须是Ord
值的列表),并报告遇到的任何错误。
您可以通过明确说明input
和output
的类型来修复该警告:
let input = [3, 1, 5, 2, 4] :: [Integer]
output = [1, 2, 3, 4, 5] :: [Integer]