0

我正在阅读 Kent Beck 的“示例测试驱动开发”一书此处提供 pdf 文件),其中他讨论了多币种货币问题并逐步设计了一个解决方案,通过引入测试并因此指定其公共方法类和反复重构以适应新的测试/行为。

他从上课Franc开始。Dollar然后考虑了这些类的接口并查看了代码并发现了重复,他将这两个类重构为都派生自一个Money类。

几次测试之后,他意识到类FrancDollar没有真正的意义,并currency为货币引入了一个字符串,最后当它需要对不同货币的货币求和时,他提出了一个Money名为的类的超类,expression它简化了对对 Money 的附加操作,例如对不同货币求和。

综上所述,在我的理解中,指导 TDD 设计过程的是对象的行为测试期望。我的问题是,由于函数式编程较少关注对象并且更多地面向类型类/特征,这是否意味着这种测试驱动的设计实践并不真正适合函数式风格?是否可以认为属性驱动的测试在设计过程中与功能风格发挥类似的作用?

编辑:

在基于属性的测试中,人们会为方法引入属性,无论给定方法的实现如何,这些属性都应该保持不变。在正常测试中,被验证的最重要的属性是实现的正确性。正如 sisyphus指出的那样,存在断言论点的先验知识从何而来的问题,因此检查正确性并不一定能给我们提供全貌。

还有其他注意它们的属性,可能会很有启发性。例如,如果我要编写一个排序函数并拥有sortedList=mySort(myList),无论实现如何,我都希望sortedListmyList具有相同的长度。如果不是这样,我可能做错了什么,即使测试可能对所有其他情况都有效。

另一个例子,一个MaxElement(list)返回Option[int]整数列表作为输入的函数,如果list不为空,则应该总是返回 Some[int]。

要检查这些属性,可以为这些方法的输入编写一个定制的生成器,然后要求测试框架生成足够的输入实例并测试属性以保证其有效性几乎可以确定。例如,在货币问题的情况下,可以编写一个生成器来生成各种类型的货币子类并检查它们的相等性,这将自动揭示出考虑贝克明确编写的一些相等性测试的必要性.

重新表述这个问题,我很想知道他是否犯了一个自然错误的原因,即明确的类FrancDollar- 他后来意识到,当他注意到两个类中某些方法的重复实现时 - 与面向对象方法密切相关在建模系统中。是否可以说函数式编程不需要这种迭代设计过程,仅仅是因为它不是从对象开始,而是进行函数分解。或者从另一个角度来看问题,测试是否会导致功能风格上的系统设计改变?

4

2 回答 2

1

公平地说,“行为”是任何人真正关心的一切——无论你是用户、测试人员、开发人员、产品负责人、销售人员还是......

Kent Beck 正在做的是说我们应该编写测试

  • 证明什么是最重要的
  • 以最重要的形式
  • 给最有可能使用被测软件的人。

因此,在 TDD Explained 中,他主要与库开发人员交谈。他的用户也是开发人员——他们正在使用一个涉及 Money 交互的库。他的用例是那些开发人员可以(或想要)使用该库做的事情。

他使用面向对象的语言,因此他提出了一种 OO 方法来尽可能解决这三个目标。如果他从纯函数式语言开始,他会提出纯函数式分解。无论哪种方式,您最终都会得到一个可用的 API,并且我(作为应用程序开发人员)可以信任我的应用程序。

Beck 试图提出的真正观点是,测试应该关注交互(或 api 或接口)而不是状态(字段、属性)。状态与实现问题有关,并且在您更改实现时会发生变化,而行为与用户想要的内容有关,并且(通常)在版本之间不可变。

纯函数式 API 和纯 OO API 方法之间通常存在差异,但 Beck 的方法实际上是相同的——我们关心的是当用户说“如果我有 20 美元那么有多少欧元”时会发生什么平等的'?

编辑:

因此,就“基于属性的开发”而言,“属性”是对方法应如何返回其值的规范。要自信地做到这一点,您通常需要对算法本身进行完整的实现。在这些情况下,您的测试代码需要能够完成生产代码所做的事情。从前提条件的角度来看这很好,因为这意味着您的测试只是参数化测试的一种形式,但它会导致引导问题 - 您如何确保您的测试实现是正确的?要么你已经有了一个(所以你应该在生产中使用它)或者你需要构建一个(所以......你如何得到它......)。

现在,有一些类型的测试(对于某些类型的事物)更容易验证,而不是通过算法参数化。对于一些更 NP 类型的算法(例如旅行商问题)来说,这当然是正确的。

但最终,从功能与面向对象的角度来看,这并不重要。无论您是使用现有方法来决定对象方法的正确性,还是使用一组有价值的测试示例来给您信心,都不是太重要。您仍然可以采用 OO 或 FP 视角。

所以事情是这样的——TDD(a la Beck)和你的 BDD 概念都是关于考虑问题解决空间的重要方面,从而使实现算法更好。他们要求您专注于有价值的示例(或不连续性)。

于 2017-01-18T02:43:52.110 回答
0

这是一个见仁见智的问题,哪个更好。这个或那个。

我的看法是,使用行为驱动开发 (BDD) 来驱动使用函数式编程语言或面向对象的编程语言开发的系统没有任何矛盾。归根结底,无论系统如何实施,它都有行为。

使用房地产驱动开发可能是也可能不是一个很好的补充。我想这取决于用例。我很难理解应该如何对业务流程使用基于属性的测试。这使我得出结论,在某些情况下,我看不到如何使用基于属性的测试,而同时我可以看到 BDD 的用途。

像往常一样,这取决于。

于 2017-01-16T19:38:40.357 回答