【问题标题】:How do I write QuickCheck tests that don't mimic implementation of the function?如何编写不模仿函数实现的 QuickCheck 测试?
【发布时间】:2014-02-16 02:08:46
【问题描述】:

我正在使用 Haskell 和 QuickCheck 为以下函数编写测试:

{-| Given a list of points and a direction, find the point furthest
along in that direction. -}

fn :: (Eq a, Ord a, DotProd a) => [a] -> a -> a
fn pnts dir = pnts !! index
    where index = fromJust $ elemIndex (maximum dotproducts) dotproducts
          dotproducts = map (dot dir) pnts

我相信这个实现是正确的,因为它不是一个太复杂的函数。但是,我想使用 QuickCheck 来测试一些边缘情况。

但是,我遇到的问题是,当我定义我的 QuickCheck 测试时,它们与我正在测试的函数相同。

如何在 QuickCheck 中编写一个测试来测试函数的用途而不重复其实现?

【问题讨论】:

  • 如果有人觉得这个问题太笼统,请考虑这是一个专门针对函数fn的问题。
  • 如果您能分享一些关于您的问题的更多信息,例如特定的不充分测试、您对它的期望以及 DotProd 类型类的来源,将会有所帮助。
  • 你能写一个Arbitrary 吗?一个方向?如果是,那么随机生成的点的什么性质不令人满意?
  • 请添加更多信息,以便您的代码为self-contained。特别是DotProd 的定义及其一些实例。如果您添加了您尝试过的 QuickCheck 测试,也会有所帮助。
  • 编码提示:查看Data.List 中的maximumBy 函数。使用fromJust 是不安全的,因为它会引发异常。

标签: unit-testing haskell testing quickcheck


【解决方案1】:

如何在 QuickCheck 中编写一个测试来测试函数的用途而不重复其实现?

首先,请注意,有时,表明函数根据其当前实现运行的快速检查属性并非完全没有价值。如果您更改了实现,您可以将其用于回归测试。例如,如果您优化 fn 的定义以使用巧妙的数据结构,则基于旧的、更直接的实现的 Quickcheck 属性可能会有所帮助。

其次,您通常希望 Quickcheck 属性检查函数的高级属性和声明性属性,而实现通常是较低级别且更直接可执行的。在这种情况下,您可以指定如下属性:

  • 对于点 ps 和方向 d 的所有列表,点 fn ps d 在列表 ps 中。

  • 对于所有点 ps、方向 d 和所有点 p 在 ps 中的列表,点 p 在 d 方向上不比点 fn ps d 更远。

  • 对于所有点 p 和对于所有方向 d,fn [p, origin] d 是 p。

我不完全确定底层几何,所以我的例子可能很愚蠢。但我希望这些示例传达了总体思路:快速检查属性可以检查规范的属性“在一个方向上更远”,而无需提及特定算法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 2021-06-10
    • 2017-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    相关资源
    最近更新 更多