Haskell QuickCheck最佳实践(特别是在测试类型类时) [英] Haskell QuickCheck best practices (especially when testing type classes)

查看:276
本文介绍了Haskell QuickCheck最佳实践(特别是在测试类型类时)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚开始使用QuickCheck和一堆Haskell代码。我知道,我落后于时代。这个问题是一个双向的问题:

首先,快速检查的一般最佳做法是什么?到目前为止,我已经找到了以下内容:


  • 为您的测试命名为prop_ *(令人讨厌,因为其他所有内容都是camelCase)
  • >
  • 测试导出的代码(如果您正在测试内部结构,您可能会犯错误)
  • 测试属性,而不是示例

    • 不要说 X超出范围,Y在范围内

    • 相反,比如如果x超出范围,则标准化x≠x (或其他某些此类属性)

    • ul>

      但我仍然在抓住其他最佳实践。特别是:


      • 属性保存在哪里?

        • test / 目录中的相同文件?

        • ? (如果是这样,那么你如何导入 src / 中的内容?)

        • 属性/在 src


      $ b下的
      $ b

      最重要的是,我们如何倾向于测试类型类的属性?例如,考虑以下(简化)类型的类:

        class Gen a where 
      next :: a - > ; a
      prev :: a - > a

      我想测试属性∀x:prev(next x)== x 。当然,这涉及到为每个实例编写测试。为每个实例编写相同的属性非常繁琐,特别是当测试更复杂时。什么是推广此类测试的标准方法?

      我相信 prop _ 惯例来自QC随脚本运行所有以 prop _ 开头的函数作为测试。因此,没有真正的理由这么做,但是它 prop_foo )。



      测试内部结构没有任何问题。有两种方法可以这样做:


      • 将属性放在与内部相同的模块中。这使模块变得更大,并且需要项目对QC的无条件依赖(除非您使用CPP hackery)。

      • 有一个非导出模块的内部,其功能实际上是从另一个模块重新导出的。然后,您可以将内部模块导入到定义QC属性的模块中,并且如果使用.cabal文件中指定的标志,则该模块仅被构建(并且具有QC依赖性)。


      如果您的项目很大,然后分开 src / test / 目录可能是有用的(尽管有区别可能会阻止你测试内部)。但是如果你的项目不是那么大(并且无论如何都驻留在一个整体模块层次结构中),那么就没有必要像这样分割它。



      正如Norman拉姆齐在他的回答中表示,对于类型类,您可以将属性定义为类型类中并相应地使用。


      I've just started using QuickCheck with a bunch of Haskell code. I'm behind the times, I know. This question is a two-parter:

      Firstly, what are the general best-practices for Quick Check? So far, I've picked up the following:

      • Name your tests prop_* (annoying, because everything else is camelCase)
      • Test exported code (if you're testing internals you're likely doing it wrong)
      • Test properties, not examples
        • Don't say X is out of range, Y is in range
        • Instead, say if x is out of range, normalize x ≠ x (or some other such property)

      But I'm still grasping at other best practices. Particularly:

      • Where are properties kept?
        • The same file?
        • in a test/ directory? (If so, then how do you import the stuff in src/?)
        • in a Properties/ directory under src?

      Most importantly, how do we tend to go about testing properties on type classes? For example, consider the following (simplified) type class:

      class Gen a where
          next :: a -> a
          prev :: a -> a
      

      I'd like to test the property ∀ x: prev (next x) == x. Of course, this involves writing tests for each instance. It's tedious to write the same property for each instance, especially when the test is more complicated. What's the standard way to generalize such tests?

      解决方案

      I believe the prop_ convention came from QC coming with a script that ran all functions that started with prop_ as tests. So there's no real reason to do so, but it does visually stand out (so the property for a function foo is prop_foo).

      And there's nothing wrong with testing internals. There are two ways of doing so:

      • Put the properties in the same module as the internals. This makes the module bigger, and requires an unconditional dependency on QC for the project (unless you use CPP hackery).

      • Have internals in a non-exported module, with the functions to actually be exported re-exported from another module. Then you can import the internal module into one that defines the QC properties, and that module is only built (and has a QC dependency) if a flag specified in the .cabal file is used.

      If your project is large, then having separate src/ and test/ directories may be useful (though having a distinction may prevent you from testing internals). But if your project isn't all that big (and resides under one overall module hierarchy anyway), then there's no real need to split it up like that.

      As Norman Ramsey said in his answer, for type classes you can just define the property as being on the typeclass and use accordingly.

      这篇关于Haskell QuickCheck最佳实践(特别是在测试类型类时)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆