Ruby -> Haskell 单元测试和自动化验收测试

4
我是一名具有多种语言背景的程序员,但最近我专注于Ruby/Rails,并对学习一些Haskell感兴趣。我也稍微研究了一下Closure(不过只是一些基础的东西)。
我的当前首选方法是使用像Gherkin/Cucumber这样的工具,使用业务价值语言编写高级别的测试,然后使用RSpec 或 Minitest之类的工具来开发小型组件,以此来开发新的Ruby应用程序。那么,开发新的Haskell应用程序的最常见的类似工具集和策略是什么?
回答者:请耐心等待我的点赞和采纳答案。我必须实际上在Haskell中进行一些工作才能做出任何评估。谢谢。

1
我认为一般来说,你会发现在Haskell中采用TDD的情况比Ruby少,特别是编译器会移除掉很多在Ruby中需要进行单元测试的东西。当我寻找Haskell测试框架时,我发现了这个答案,同时《Real World Haskell》第12章也介绍了测试和QA,推荐使用QuickCheck和HPC。 - kieran
@kieran 感谢提供的链接。如果语言可以减少很多测试需求,那么这是很好的事情,但我认为这只意味着少做了一些单元测试,并不代表 TDD 失去了它的价值。另外,关于 AATs 呢?HSpec 提到了“接受测试驱动规划”,但是我并没有看到类似 Cucumber 或 Fitness 的东西。我在 Github 上看到了一个 cucumber-haskell 项目,但它看起来还处于早期开发阶段。 - Steve Jorgensen
当然,我没有看到像Haskell的Fitnesse这样的东西,这就是为什么我只是评论而不是回答的原因。我喜欢在.NET中使用TDD w/ Fitnesse进行工作,但是我在Haskell上的经验远远不是面向测试的系统,而是更喜欢将小型的类型/数据驱动正确函数组合成较大的系统,其中纯度等保证了组合后的正确性。也许值得一提的是不同的方法,但无论如何,我都会关注这个问题。 - kieran
Haskell的低级TDD问题在于,为了编写有意义的测试,您需要知道正在测试的内容的类型。对于Haskell中基本的通用功能单元(特别是如果您设计以尽可能多地表达代码属性的类型),弄清楚类型通常是最困难的部分!一种常见的经验是,一旦您正确理解了类型,代码几乎可以自己编写。如果是这种情况,那么组件开发的实质部分(了解类型)是编写测试的先决条件。 - Ben
3个回答

7

在 Haskell 应用程序中,真正的可信来源通常是类型系统。使用 QuickCheck 和 Hspec 可以提高代码符合预期的保证,但这只是辅助手段。


5
+1 给 Mark。这是迄今为止最常见的设计方法:在类型系统中设计业务逻辑;然后编写不可用类型表达的不变量作为 QuickCheck 属性。对于剩下的内容,使用 HUnit 等单元测试。 - Don Stewart
AAT通常使用非程序员易懂的语言编写,并涵盖可能涉及与用户和/或其他系统进行多次交互以及对持久数据(文件、数据库等)进行多次更改的情况。 - Steve Jorgensen
2
关于TDD:(0)许多动态语言专家没有意识到像GHC这样的类型系统可以强制执行多少内容。(我也是如此。)(1)测试也是如此,但表达能力强的类型/证明具有静态优势,因此排除了大量错误的类别;(2)之前尝试过在Ruby中编程后,我更加自信地依赖纯度和丰富的类型系统(如果需要,稍后再进行测试),而不是使用测试来尝试覆盖类型系统排除的所有错误代码路径。(3)类型和/或证明驱动的开发达到了相同的目标,静态保证有助于避免虚假API。 - Fixnum
我认为AAT仍然是TDD中非常有趣的价值,这也是类型系统无法复制的。尽管如此,使用类型语言以高级别描述系统的业务逻辑可以用于确定程序目标,然后可以立即进行内部一致性检查(在编写任何实现之前)。GHC的类型检查器比您想象的要强大得多。我会说它可以捕获比您想象的更多错误,并且提供了重构的信心,而TDD甚至不能接近。 - J. Abrahamson
承认我仍在争论一门我从未使用过的语言,但我不相信某些语言的特性会削弱TDD的好处。首先,TDD是一种设计/文档化的行为。它不仅仅是证明正确性,还要编写将调用该单元的代码,并在此过程中决定该单元的职责应该是什么,对于该单元来说什么是一个好的描述性名称等等。就简单地证明正确性而言,我也想起了Knuth的名言:“小心上述代码中的错误;我只证明了它的正确性,而没有尝试过它。” - Steve Jorgensen
显示剩余3条评论

2

对于基于故事的自动化验收测试在Haskell中,您有两个主要选择:

  • chuchu(一个不完整的Cucumber / Gherkin实现,使用Haskell本身编写,Hackage页面
  • 使用Wire协议的Cucumber,并使用Ruby编写测试

当然,HSpec可以填补基于规范的验收测试角色。

使用类似QuickCheck和Smallcheck等库进行基于属性的测试可以获得更好的结果,而不是使用TDD。


1
据我所知,Haskell没有类似于Cucumber的工具。最接近您要寻找的可能是HSpec,它类似于RSpec。
以下是HSpec网站上的一个示例verbatim from the HSpec site
import Test.Hspec
import Test.QuickCheck
import Control.Exception (evaluate)

main :: IO ()
main = hspec $ do
  describe "Prelude.head" $ do
    it "returns the first element of a list" $ do
      head [23 ..] `shouldBe` (23 :: Int)

    it "returns the first element of an *arbitrary* list" $
      property $ \x xs -> head (x:xs) == (x :: Int)

    it "throws an exception if used with an empty list" $ do
      evaluate (head []) `shouldThrow` anyException

Which produces

Prelude.head
  - returns the first element of a list
  - returns the first element of an *arbitrary* list
  - throws an exception if used with an empty list

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接