1.4.2 放弃追求完美

有些软件的功能非常简单,比如简单的数学运算,或者统计用户输入字符的数量;有些软件的功能非常复杂,比如操作系统,或者汽车的自动驾驶算法等。

对于复杂的软件,因为它们有很高的复杂度,所以我们很容易理解它们为什么很难完美。

那么,对于特别简单的软件,我们是不是可以进行彻底的测试,保证它们是完美的呢?

这是不可能的!即使拥有无限的预算,我们也无法做到这一点。

我们来分析一个简单的程序:接受用户输入的字符串,统计其中的字符数量。比如,对于输入字符串Python,统计结果为6;对于test,统计结果为4……

要确保这个程序是完美的,我们就需要验证所有可能的输入。用户可能输入一个简单的字符,也可能输入整部《三国演义》,我们无法预知用户的输入是什么。用户输入字符的数量在理论上可以是任意一个自然数,而自然数的数量是无穷大的,我们无法把所有的情况都覆盖到。

如果把问题简化,限定用户最多只能输入10个字符,超过10个字符就告知用户无法处理,这种情况下,我们能否进行彻底的测试?

这也是不可能的!在用户输入超过10个字符的情况下,程序真的会告知用户无法处理吗?为了确认这一点,我们需要把所有超过10个字符的输入都覆盖到,确保程序会告知无法处理,而不是意外地返回一个错误的统计值。大于10的自然数仍然是无穷多的,我们还是无法把所有的情况都覆盖到。

如果我们把问题再度简化,只测试字符数量在10个以内的有效输入呢?

世界上有许多语言和文字,unicode编码可以涵盖世界上所有语言的字符,包含字符的数量级大概是一百万。粗略地估算下来,用户输入字符数量为1个的情况,我们有100万个测试要验证;用户输入字符数量为10个的情况,我们有100万的10次方个测试要验证。只要有一个测试没有被覆盖到,我们就不能说在这种情况下程序可以正常工作,也就不敢说程序没有bug。

在现实世界中,大部分软件程序比这个字符统计的程序要复杂得多,它们一定有bug没有被发现,或者有bug被发现了却没有被修复,它们肯定称不上完美,却仍然达到了较高的软件质量,这当然不是因为它们把测试做得非常彻底,而是因为放弃追求不切实际的完美,在预算范围内采用了合适的测试策略,得到较高的投资回报率。