单元测试 – 如何在功能编程中编写好的单元测试

我正在使用函数而不是类,我发现我不知道它依赖的另一个函数是一个依赖关系,应该单独进行单元测试,或者内部实现细节不应该.你怎么知道是哪一个?

一个上下文:我正在编写一个非常简单的Lisp解释器,它具有一个eval()函数.它将有很多的责任,实际上太多,比如评估符号不同于列表(所有其他的评估本身).评估符号时,它有自己的复杂工作流程(环境查找),评估列表时会更复杂,因为列表可以是一个宏,函数或特殊格式,每一个都有自己的复杂工作流程一套责任

我不知道我的eval_symbol()和eval_list()函数是否应该被认为是eval()的内部实现细节,应该通过eval()自己的单元测试来测试,或者是它们自己的本身的真正的依赖关系独立于eval()的单元测试进行测试.

最佳答案
“单元测试”概念的重要动机是控制所需测试用例的组合爆炸.我们来看看eval,eval_symbol和eval_list的例子.

在eval_symbol的情况下,我们将要测试符号绑定的偶然事件:

>遗漏(即符号未绑定)
>在全球环境中
>直接在当前的环境中
>从包含环境继承
>遮蔽另一个绑定
> …等等

在eval_list的情况下,我们将要测试(除此之外)当列表的函数位置包含一个符号时会发生什么:

>没有函数或宏绑定
>一个函数绑定
>一个宏绑定

eval_list会在需要符号绑定的时候调用eval_symbol(假设是LISP-1).假设eval_list有eval_symbol和L符号相关测试用例的S个测试用例.如果我们单独测试这些功能,我们可以避开大致S L符号相关的测试用例.但是,如果我们希望将eval_list视为一个黑匣子,并且在没有任何知识的情况下,在内部使用eval_symbol的方式进行详尽的测试,那么我们面临着S x L符号相关的测试用例(例如全局函数绑定,全局宏绑定,本地函数绑定,本地宏绑定,继承函数绑定,继承的宏绑定等).这还有更多的情况. eval更糟糕:作为一个黑盒子,组合的数量可能变得非常大 – 因此组合爆炸术语.

所以我们面临着理论上的纯粹性与实际的实际性的选择.毫无疑问,只运行“公共API”(在这种情况下是eval)的一整套测试用例给出了最大的信心,即没有错误.毕竟,通过行使一切可能的组合,我们可能会产生微妙的整合错误.然而,这种组合的数量可能非常大,以至于妨碍这种测试.更不用说程序员可能会错误地(或疯狂地)审查大量仅以微妙方式不同的测试用例.通过单元测试较小的内部组件,可以大大减少所需测试用例的数量,同时仍保持对结果的高度置信度 – 一个实际的解决方案.

所以,我认为单元测试的粒度的确定方法是:如果测试用例的数量不舒服,开始寻找较小的单元进行测试.

在目前的情况下,我绝对主张将eval,eval-list和eval-symbol作为单独的单元进行测试,正是因为组合爆炸.在编写eval-list的测试时,您可以依靠eval-symbol进行稳定的操作,并将注意力集中在eval-list自身添加的功能上. eval列表中还可能有其他可测试单元,例如eval-function,eval-macro,eval-lambda,eval-arglist等.

转载注明原文:单元测试 – 如何在功能编程中编写好的单元测试 - 代码日志