【问题标题】:How to write data-driven tests using Hspec?如何使用 Hspec 编写数据驱动的测试?
【发布时间】:2017-12-30 17:33:25
【问题描述】:

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

【问题讨论】:

    标签: haskell hspec


    【解决方案1】:

    您可以定义一个高阶函数,例如:

    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)
    

    其中sortData.List 版本,bubblesort 是您正在测试的实现。然后 QuickCheck 将生成 100 个符合约束的列表(必须是 Ord 值的列表),并报告遇到的任何错误。


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

    let input  = [3, 1, 5, 2, 4] :: [Integer]
        output = [1, 2, 3, 4, 5] :: [Integer]
    

    【讨论】:

    • 赞成,但编写更多代码来实现单元测试框架应开箱即用的功能并不是我想要的。并且指定类型确实消除了警告,但我想了解它为什么首先出现。很明显input[Integer] - 否则聪明的编译器有什么问题?
    • 您可以查看QuickCheck 以提供更好的数据驱动的东西,它可以生成随机测试输入。这是我个人使用的。对于该错误,这些值的类型可能是 IntegerInt
    • 谢谢,我会看看 quickcheck,虽然它似乎是属性驱动的测试,一种不同的方法。 [Int] 也适用于 inputoutput - 我忘记了 Int vs Integer
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多