【问题标题】:Writing test cases in Haskell for differing types在 Haskell 中为不同类型编写测试用例
【发布时间】:2017-07-09 20:13:16
【问题描述】:

我创建了一个库来创建“类似列表”的序列,其中实现了许多 Prelude 风格的函数。我想为此编写一些测试用例,以确保我的库产生正确的输出,我认为最简单的方法是编写一些函数,将结果转换为列表并将它们与 Prelude 结果进行比较。假设我们有这个:

import qualified MyLibrary as ML
import qualified Prelude as P

例如,我可能需要以下测试用例:

P.take 5 (P.enumFrom 1) == toList (ML.take 5 (ML.enumFrom 1))

注意ML.enumFrom 不输出列表,它输出它自己的数据类型。

上面的工作正常,但请注意我是如何“重复自己”的(TM)。我必须确保左侧和右侧相同,否则我的测试用例是错误的。

有没有一种很好的方法来编写这样的测试用例,这样我就不必重复自己了?

【问题讨论】:

  • 当您的测试定义为“重复自身”以比较两种机制时,我认为您并不是真正“重复自己”。
  • 理想情况下,所有测试都采用一个参数来确定使用哪个函数,所以我可以有一个 doTest 函数,类似于 doTest test = test True == toList (test False) 或类似的东西,但我还没有找到方法在没有类型检查器讨厌我的情况下做到这一点。
  • @Clinton:我认为如果不实例化一个常见的class 或者可能使用模板 haskell(我没有经验),你就无法实现这一目标

标签: unit-testing haskell testing


【解决方案1】:

P.takeML.take 等的第一个问题只是看起来相似——实际上它们是完全不相关的函数,编译器对它们的共同行为一无所知。所以,正如@jd823592 所建议的那样,我们需要用一个类型类对它们进行分组(我使用了一个简单的newtype 包装器,因此该示例是可编译的):

import Prelude hiding (take, enumFrom)
import qualified Prelude as P (take, enumFrom)

newtype MySeq a = MySeq [a]

class Sequence s where
    take :: Int -> s a -> s a
    enumFrom :: Enum a => a -> s a
    toList :: s a -> [a]

instance Sequence MySeq where
    take n (MySeq xs) = MySeq (P.take n xs)
    enumFrom n = MySeq (P.enumFrom n)
    toList (MySeq xs) = xs

instance Sequence [] where
    take = P.take
    enumFrom = P.enumFrom
    toList = id

然后我们将尝试使用类定义中现在统一的函数来定义一些测试。它们可能只生成任何类型的Sequence,然后我们将强制它们生成显式类型。

test1 = doTest (take 5 $ enumFrom 1) -- the part in brackets is polymorphic

doTest :: (Eq a, Sequence s) => s a -> Bool
doTest test = ???

现在第二个问题是我们将多态函数作为参数传递,然后需要用不同类型的参数(在这种情况下为[a]MySeq a)实例化它。在标准的 Haskell 2010 中这是不可能的,但我们可以利用 Rank2 (or RankN) extension:

{-# LANGUAGE Rank2Types #-}

<...>

doTest :: forall a . Eq a => (forall s . Sequence s => s a) -> Bool
doTest test = (test `asTypeOf` dummy1) == toList (test `asTypeOf` dummy2) where
    dummy1 :: Eq a => [a]
    dummy1 = undefined
    dummy2 :: Eq a => MySeq a
    dummy2 = undefined

这个解决方案有点笨拙,但仍然有效。请随时改进。

【讨论】:

    猜你喜欢
    • 2012-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-03
    相关资源
    最近更新 更多