“我正在考虑更多的 TDD,比如在 OOP 语言中。这样的事情在 Haskell 中可能吗?”
一个更好的问题是“在 Haskell 中是否有必要这样做?” ;-)
[我意识到这不是你真正问的问题。随意忽略这个答案。]
在 OO 语言中,我们构建与其他对象对话以完成其工作的对象。为了测试这样的对象,我们构建了一堆假对象,将真实对象与假对象挂钩,运行我们想要测试的方法,并断言它使用预期的输入调用伪造的方法等。
在 Haskell 中,我们编写函数。纯函数唯一要做的就是接受一些输入并产生一些输出。所以测试的方法就是运行这个东西,给它提供已知的输入并检查它是否返回已知的输出。它在执行此操作的过程中调用了哪些其他函数并不重要;我们只关心答案是否正确。
特别是,我们通常在 OOP 中不这样做的原因是调用一些任意方法可能会导致“真正的工作”发生——读取或写入磁盘文件、打开网络连接、与数据库和其他服务器通信等。如果你'只是测试你的代码的一部分,你不希望测试依赖于某个数据库是否在某个地方的真实网络服务器上运行;您只想测试一小部分代码。
使用 Haskell,我们将任何可能影响现实世界的事物与仅进行数据转换的事物区分开来。测试仅在内存中转换数据的东西非常简单!(总的来说,测试与现实世界交互的代码部分仍然很困难。但希望这些部分现在非常小。)
选择的 Haskell 测试风格似乎是基于属性的测试。例如,如果你有一个求解方程的函数,你编写一个 QuickCheck 属性,它随机生成 100 个方程,并且对于每个方程,它检查返回的数字是否真正解决了原始方程。这是一小部分代码,可以自动测试几乎所有你想知道的东西!(但不完全是:您需要确保“随机”选择的方程式实际上测试了您关心的所有代码路径。)