我最近获得了测试宗教,并且主要从事单元测试。我编写单元测试,说明函数在某些情况下工作,特别是使用我正在使用的确切输入。我可以做一些单元测试来练习这个功能。尽管如此,除了函数在我测试的场景下做了我期望它做的事情之外,我还没有真正证明过。可能还有其他我没有想到的输入和情景,并且考虑边缘情况是昂贵的,特别是在边缘。
这对我来说并不是很令人满意。当我开始考虑必须提出测试以满足分支和路径覆盖以及集成测试时,预期的排列会变得有点令人抓狂。
所以,我的问题是,如何证明(在证明数学定理的同一方面)一个函数是有效的(并且,在一个完美的世界中,将这些'证明'组合成一个系统工作的证据) ?
是否有某个测试领域涵盖了一种方法,在这种方法中,您试图通过证明系统的所有功能都有效来证明系统正常工作?学术界以外的任何人都不愿意这样做吗?是否有工具和技术可以提供帮助?
我意识到我对“工作”一词的使用并不准确。我想我的意思是,当一个函数执行某些规范(书面或暗示)表明它应该做什么以及除此之外什么都不做的时候,函数是有效的。
注意,我不是数学家,只是程序员。
答案 0 :(得分:2)
在学术界,有一个类似于数学归纳的概念,它被称为结构归纳。但是,它仅适用于没有副作用的函数式编程语言和方法。在其他情况下,证明方法因副作用而起作用是非常困难的,如果不是不可能的话。
在TDD中,您尝试制定方法必须满足的边缘情况才有效,但是,可能会错过这种情况。即使(非平凡)方法满足您的所有测试,也可能存在参数组合或一系列事件,您根本没想到会破坏您的代码。简单地说:这就是生活。您可以预测非平凡实现中的所有结果,但您可以确保该方法适用于特定边缘情况,期望某些情况如此前卫,您将在触摸它们时削减自己。 (zing,坏双关语)。
答案 1 :(得分:2)
听起来,您正在将工作定义为执行您希望它执行的操作的功能。或者换句话说,您想要证明您正确输入了逻辑。
那么,在这种情况下,至少假设函数的有效输入数量接近无限,你无法真正证明某些东西是正确的,你只能反驳它。因此,我们的想法是创建跨越函数各种输出的良好单元测试。它没有证明是正确的,但可以用来证明某些东西是正确的。
答案 2 :(得分:0)
证明某些东西有效的方法可以通过形式证明来完成。一些技术是众所周知的,至少在学术界是如此。我想到的是"Proof by induction"。然而,这种方法相当手动,而且如果不是简单太复杂的话,也很容易出现凡人。
另一种更易于管理的形式验证方法称为“模型检查”。使用这种方法,您可以以合适的方式表达您的软件,允许您对其执行某些检查(使用工具)。一个这样的检查可能是检查多线程应用程序中的死/活锁。 您可以执行的其他类型的检查是确保您的应用程序始终允许与同一应用程序的简单模型进行相同类型的交互,从而降低在模型和模型中犯同样错误的可能性。真正的应用。模型检查的工具可能是Spin,但有许多工具。
维基百科似乎也有一篇关于这个主题的文章:Formal Verification
答案 3 :(得分:0)
“听起来你正在将工作定义为功能,做你想做的事” 通常你也想验证一个函数没有做你不想做的事情,定义很接近但不一样,例如ADD()函数可以返回正确的答案但也打印出一些额外的调试垃圾。