0

我正在学习 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)
4

1 回答 1

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 安装)。

然后,您可以将测试定义为:

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,您的实现在哪里?然后 QuickCheck 将生成 100 个符合约束的列表(必须是值列表),并报告遇到的任何错误。Data.ListbubblesortOrd


您可能可以通过明确说明您的inputoutputs 的类型来修复该警告:

let input  = [3, 1, 5, 2, 4] :: [Integer]
    output = [1, 2, 3, 4, 5] :: [Integer]
于 2017-12-25T10:16:08.110 回答