首先说明,我对测试的了解属于从外部逐渐了解的那种,可以说基本上是外行。但是如果愿意讨论这个问题,希望不要因为我的业余,就完全否认我的说法。另外需要重申的是,我并不否定TDD,因为我认为测试更多的应该发挥一个工程上的作用,我质疑的是通过测试保证正确性。
迪斯特拉说过,测试只能证明一个事情是错的,但永远不能证明一个事情是对的。
这是一句没法否认的话。但是我心里也明白,没有必要要求形式上的、100%可以保证的正确性,关键在于代价和效果的比。如果在“正确性”上,可以得到一个比如99%的概率(请注意哪怕1%的概率,也意味着存在完全正确的可能性,只是心里比较没谱罢了),而使用某种方法的成本很低,这样的做法我完全认同。
问题在於,在复杂度足够高的某些过程上,要达到相同的概率,测试付出的代价超出了构造该过程本身甚至再加上多次、多人验证的代价,而且可能对“是否正确”这一结论引入新的不确定性。在保证正确性这一问题上,连InfoQ这种站的某些作者都指出,比如“净室开发”也可以取得至少一样好甚至更好的结果。
根据McConnell书中引用的报告,相比其它检验手段,测试的BUG检出率即便不是最少那也是相当的少了。你可以认为这是测试做得不到位,但这也揭示了测试作为一种手法,保证正确性这一部分功效,在相当多的工程中也是不可行的:因为我们只能以平均水准要求参与工程的人员。
在这方面,我觉得讨论更先进的测试手法来体现测试的优越性,太过具体,而且实际上最终指向的还是:在给定的条件下,可以保证的正确性概率是否满足要求(如果同一过程在条件之外给出完全错误的结果其实也不是不能接受的);其次,满足要求要花费的成本是多少。在这方面,我也恳请懂行的人可以给出各方面的资料,让我和其它有兴趣深入的人可以更好的了解和研讨。
对于一些过程而言,使用测试在正确性保障方面,因为在覆盖等方面本身存在着可行但成本很高或完全不可行的情况,想要达成某一较高的概率甚至是根本无法实现的(比如迪斯特拉举的例子);而这些过程很可能存在其它的检验手段可以达成目标。理解了这一点(这是进行简单的思维试验就可以弄清楚的),就知道了我这个外行在说什么。
最后强调的是,我不否认测试在工程上所起的作用;甚至在正确性这方面,在很多地方使用测试的可行性也非常高,而相应的成本会比较低。比如Knuth虽然也很不客气的否认测试作为一种手法的优越性,不过在他的具体项目中,也不是完全不使用测试的。但如果只是一味倡导,而完全忽略其中我们需要细心的思考的、可能存在的破绽,我觉得就比较不能接受了。
在本篇中,以过程作为讨论对象,是因为过程的正确是构成软件正确性最根本的基石,尤其是关键性过程的正确,我个人目前不赞成使用测试来保障(虽然还是应该根据过程的特点来决定)。另外需要注意的一点,本文讨论的是正确的概率,而不是测试的覆盖率(虽然这是影响概率的主要因素之一)。
最终,这是一个减小出错风险的效果的性价比问题,在某些过程上,是可行性的问题。另外,我觉得这个问题是一个典型的例子:我们无需深入课题内部各个细节,就可以通过分析思考学到很多的东西,甚至作出有益的判断和决定。