首页 > 解决方案 > 如何测试假设其输入来自智能构造函数的函数?

问题描述

tl;博士

我想了解如何使用Test.QuickCheck来测试其参数被传递给智能构造函数和/或假设为来自智能构造函数的函数。

长版

在一个模块中,我有一个用户定义的类型,如下所示:

newtype SpecialStr = SpecialStr { getStr :: String }

顾名思义,SpecialStr它很特别,因为被包裹String的不是“任何”字符串,但它必须满足一些属性。为了强制执行这一点,我不从模块中导出值构造函数,而是导出一个智能构造函数

specialStr :: String -> SpecialStr
specialStr str = assert (isValid str) $ SpecialStr str
  where
    isValid :: String -> Bool
    isValid = and . map (`elem` "abcdef") -- this is just an example logic

当然,我已经定义了一些与这些 s 一起操作的函数SpecialStr,例如

someFunc :: String -> [SpecialStr]
someFunc str = -- uses smart constructor
someOtherFunc :: (Int, SpecialStr) -> Whatever
someOtherFunc = -- assumes the input has been created via the smart constructor, i.e. assumes it's valid

其中可能会someFunc被输入 a String,然后输出[SpecialStr]被压缩[1..]并且结果被输入someOtherFunc,只是为了做一个随机的例子。

现在我的问题是:如何使用 测试这些功能QuickCheck

标签: unit-testinghaskellconstructorfunctional-programmingquickcheck

解决方案


有一个聪明的构造函数?编写一个智能任意实例。

instance Arbitrary SpecialStr where
    arbitrary = SpecialStr <$> listOf (choose ('a', 'f'))
    shrink (SpecialStr s) = SpecialStr (shrinkList (enumFromTo 'a') s)

然后像往常一样写你的属性。

-- check that someOtherFunc is hypermonotonic in the SpecialStrings
quickCheck (\n1 n2 s1 s2 -> someOtherFunc (n1, min s1 s2) <= someOtherFunc (n2, max s1 s2))

...管他呢。


推荐阅读