# 软件测试实质


Ron Patton所著的《软件测试》2002年的中文版，已经十五年了，但它对“软件的实质”的解释仍然是经典，这里摘录与大家分享。

__实质__，哲学中的本质，又称为“实质”是指某一对象或事物本身所必然固有的。说的通俗点也就是说软件测试的本来的面目。


<br>
#### 软件缺陷的定义                                                                                           

来看一下Ron Patton 为我们的软件缺陷所下的定义。

__1、软件没有实现产品的说明书所描述的功能。__

__2、软件实现了产品说明书描述不应有的功能。__

__3、软件执行了产品说明书没讲的操作。__

__4、软件没有实现产品说明书没讲但应该实现的功能。__

__5、从软件测试员的角度来看，软件难以理解、不易使用、运行缓慢，或者最终用户认为不对。__

为什么一个定义要这么多条来描述？这个“缺陷”的定义有这么复杂么？不，它其实并不复杂，作者只是想更加全面的来给“缺陷”下定义。

下面我们来以建一栋房子为例，来说明一下每一条定义的意思。需要说明的是没有十分完美而且一成不变的产品说明说，而且在实际项目中，它可能非常简陋，模棱两可，甚至经常变动。

__1、__ 软件没有实现产品说明书的描述的功能。房子的主人希望有一个落地的大窗户，让阳光更好的照进屋子里，而且他特意在房子的设计图纸中画出来，并且还加以说明。结果，他看到的是四面全是墙壁，只有一个小门的房子。那么对于测试人员来说，他就是一个缺陷。

__2、__ 软件实现了产品说明书中描述的不应有的功能。由于房子的主人生活在南方，天气温暖，而请来的泥瓦匠是北方的，结果给主人建造的房子具然有一个大大的取暖的烟筒，而且主人特意在房子的设计图纸中说明，自己的房子不要烟筒。那么对于测试人员来说，这也是个缺陷。

__3、__ 软件执行了产品说明书没讲的操作。与第二条类似，不同的是第二条是主人已经明确说了自己不要烟筒，而这一条强调的是在主人没说的情况下。泥瓦匠自作聪明的加了一个烟筒上去。对于测试人员来说，画蛇添足的功能同样被视为缺陷。

__4、__ 软件没有实现产品说明书没讲但应该实现的功能。房子的主要对屋子的高度、格局，材料，颜色描述的非常清楚。泥瓦匠在建造房子的时候发现，主人没有提地基这回事，为了使房子牢固，所以，所有的房子都是必须要先打地基的，虽然主人没有说，但地基的功能必须要做。如果因为没有描述没有去做，但这又一件必须去做的事。对于测试人员来说，也可以视其这缺陷。

__5、__ 从软件测试员的角度看，软件难以理解、不易使用、运行缓慢，或者最终用户认为不对。软件测试员是软件除了测试软件运行的缺陷，同样是作为一个用户在再对软件进行使用。如果感觉自己都很难使用，或软件效率非常低且界面丑陋等情况，也可以认为其存在缺陷。或者是最终用户拿到产品时发现这根本不是自己想要的东西，也可以现其为缺陷。当然，用户说不是自己想要的东西，也不能凭借一面之词，可以拿合约，产品说明书来评估。

<br>
#### 完全测试程序的可能性                                                                         


初做软件测试者可能认为拿到软件后就可以进行完全测试了，找出所有软件缺陷，并使软件完美。遗憾的是这是不可能的，我们无法对一个软件进行完全测试，即使最简单的程序也不行。主要原因如下：

* 输入量太大
* 输出结果太多
* 软件实现的途径太多
* 软件说明书没有客观标准。从不同的角度看，软件缺陷的标准不同

以上的“太多”的可能性加在一起，致使测试条件难以确定。

以126邮箱为登录测试为例，其用户长度为50个字符，密码确实不太好计算（因为都是*号），所以这里也按50个字符来计算。

在输入正确用户名的情况下：
```
1、输入正确的密码名是还否可以登录，

2、那么错误输入0 呢？1呢？2呢？......直到

99999999999999999999999999999999999999999999999999 ，

3、如果密码不是数字，而是字符呢，a 、b、c ... aa、bb 、cc .....

4、如果是大写呢 A 、B、C.... AA 、BB、CC.....

5、如果是大小写呢 Aa、Ab ....

6、如果是小写+数字呢 1a 、1b 、1c ....2a 、2b 、2c.....

7、如果是大写+数字呢 1A 、1B 、1Cc....2A 、2A 、2A.....

8、如果是大写+小写+数字呢 1Aa 、1Bb 、1Cc ....1Aa 、1Bb 、1Cc.....

9、如果有特殊字符呢 @#￥%……&*

10、如果输入字符有空格呢  a b、adbc   ee......

11、如果是其它字符+大小写字母+数字呢+空格呢 ！@#&+123AIBKIkklzcb ......

......

12、再换正确的密码，错误的文件名再来一次。

13、用错误的用户名和密码再把上面的情况验证一次。（这样会匹配到所有的用户名密码）

14、什么都不输，直接点击登录
```

这样穷举下去，就算是计算机也可能需要运行很久。__如果觉得某些测试条件是重复的或者是无必要的，而将其剔除，那么就不能称为完全测试。__


<br>
#### 软件测试是有风险的                                                                                

你已经知道了不进行完全测试是有风险的，如果决定不去测试所有的情况，那么我们就选择了风险。在上面的邮箱登录的例子中，（假如）由于程序所使用语言的特点，有些字符在存储的时候会被转义，如: &会被转义为--存储，一个叫“&&” 用户，一个叫“--”的用户，使用了相同的密码，碰巧程序员没考虑到这种情况，那么程序该如何登录呢？

对于一个免费开放的邮箱来说，会有成千上万的用户每天都有用户注册登录，如果有用户遇到了上面的问题呢？程序该如何处理？当然，对于一个邮箱系统，你可能不以为然，他的修复速度与成本都不算高，假如，这个用户有非常保密且重要的邮件，结果被别一个用户登录查看了呢？假如这不是一个邮箱系统，而是一个银行系统呢？那有可能用户的财产就会受到损失。（相比较而言，互联网产品（B/S架构）比客户端产品（C/S架构）的修复速度与成本要低。

这样说有些耸人听闻，又不能全部测试，不测试又会漏掉软件缺陷。软件终归要分布的，此时测试就要停止，但是如果这么快停止下来，还有测试没做。怎么办？

![](http://img.testclass.net/test_work.jpg)

如上图所示，纵轴是表示缺陷的数量，横轴表示测试工作量。缺陷的数量随着测试工作的进展在不段减少；但测试费用也随着工作量在不段提高。

也就是说要想发现更多的缺陷就必须投入更多费用（这个费用包括时间、人力，物力）， 对一个新项目，我们前提可能1天发现10个缺陷。到后面可能10天发现1个缺陷，或者发现一个缺陷所需要的时间更长，我们有必要为发现一个缺陷而继续增加费用么？本来就不存在完美的产品，我们的目标是找到最合适的测试量，使投入（测试费用）与回报（修复缺陷数）达到最优。

<br>
#### 测试无法显示潜在的软件缺陷                                                                     

仔细理解一下这个标题。当测试人员对一个软件进行测试时，他发现了很多缺陷，功能的，界面的，兼容性能。然后，测试人员可以好不忧郁的说，这个软件存在缺陷。

当测试人员又对另一个软件进行测试时，他用尽各种测试方法，测遍所有功能（当然，这是不可能，上面已经说了无法完全测试），他投入了大量的时间和精力却最终没有发现一个缺陷。那么测试人员不能保证这个软件是没缺陷的，当然，他更无法去报告这些潜伏的缺陷。也就是说测试人员只能报告已经发现的缺陷，对于未知的谁也不能肯定。

（这也是测试人员遭受质疑的地方，你既然不能保证软件的质量，要你何用。测试人员可以提高软件的质量，至于能提高多少，全凭测试人员的能力决定了。不像开发人员对于一个功能的实现，能或不能是很明确的两个答案。）

<br>
#### 找到的软件缺陷越多，说明软件的缺陷越多

我们先来体会下面两句话。

__“找到的软件缺陷越多，说明软件遗留的缺陷越少”__

__“找到的软件缺陷越少，说明软件遗留的缺陷越少”__

不管是开发还是测试，我们期望软件遗留的缺陷少。但是上面的两句话都不成立。我们发现缺陷的多少和最终软件遗留的缺陷多少毫无关系。那么为什么会有上面两种推断呢？

“找到的软件缺陷越多，说明软件遗留的缺陷越少”这种情况，假设缺陷在一定数量的情况下，测试人员业务非常精通，测试极其认真，发现越多的缺陷 ，说明还遗留的缺陷就越少。那么，我也可以假设随便这么一测，就发现这么多缺陷，那这个软件应该还有很多。

“找到的软件缺陷越少，说明软件遗留的缺陷越少”这种情况，假设开发人员经验非常丰富，而且工作非常认真，测试人员花费了很大的时间和精力都不能找到缺陷，说明软件本身的质量很好，也就是说其本身遗留的缺陷越少。那么，我也可以假设为，是不是测试对业务不够熟悉，经验不够丰富，为什么发现不了缺陷。那么可能软件遗留的缺陷还有很多，只是我没有发现。

更严谨说法，或者更准确的说法是“找到的软件缺陷越多，只能说明软件的缺陷越多。”我们发现的缺陷越多，只能说明软件的缺陷多。并无法正明软件还遗留的缺陷的多少。

当然，也并不是无法评估软件遗留缺陷的多少，我们可以根据开人员的工作经验与技术能力，测试人员的工作经验，测试技能，对业务的熟悉程度以及以往完的成项目质量进行评估。

<br>
#### 并非所有软件缺陷都能修复

“每一个测试人员都一颗追求完美的心”，当我们发现了一个缺陷时，我们希望它能够被修复，我们不能容忍被发现的缺陷眼睁睁的存在着而无法得到修复。在软件测试中，令人沮丧的现实是，即使拼尽全力，也不是所有的软件缺陷都能修复。

这并不意味着软件测试员未达到目的，或者项目小组将发布质量有缺陷的产品。其真正的含义是要软件测试员具备本文开头（缺陷的定义）中所描述的测试的素质---进行良好的判断，搞清楚在什么情况下不能追求完美。项目小组需要每对一个软件缺陷进行取舍，根据风险决定哪些要修复，哪些不要。

不需要修复软件缺陷的原因：


* __没有足够的时间__：在任何一个项目中，通常是软件功能较多，而代码编写人员和软件测试人员较少，而且在项目进度中没有给测试留出足够的空间。

* __不算真正的缺陷__：或者有人说，这不算缺陷，而是一项新的功能。在某些特殊场合，错误理解、测试错误或说明书变更会把软件缺陷当作附加功能来对待。

* __目前技术无法解决__：你不会相信，人类有丰富的想象力，很多时候是受制于技术上无法实现。

* __修复的风险太大__：这种情况非常常见。软件本身是脆弱的、难以理清头绪。修复一个软件缺陷可能导致其它软件缺陷出现。在紧迫的产品发布进度压力之后，修复软件将冒引入更多缺陷的情况下。我们只能不去理睬现有的缺陷。

* __修复成本太高__：当我们使用一种技术去完成一项工作，当技术将要完成的时候发现一个缺陷无法解决，需要换用另一个技术才能有效规避这个缺陷。那这个修复成本将非常高。迫于时间与成本的压力。我们需要暂时不去理会。

* __不值得修复__：虽然有些不中听，但这是真的。不常出现的软件缺陷和在不常用的功能中出现的缺陷，或都出现也不会造成什么影响，那么就不值得去修复。这些都要归结为商业风决策。

<br>
#### 软件说明书不断变化

软件开发者面临一个难题。整个行业变化太快，去年还很时髦的产品今年就过时了，同时，软件变得更庞大、更复杂，功能越来越多，导致软件开发周期不断变长。这两种反作用力形成了矛盾，结果是产品说明书一变再变。

除了紧跟变化没有其他方法。假定我们的产品有一个不得更改的最终产品说明书。经过两年按部就班的开发快要完工时，结果竞争对也手发布了一个产品，结果从功能、性能、用户体验都要优于我们即将完工的产品。我们是继续完成一个失去竞争力的产品，还是重新讨论产品功能，重写产品需求，并开发修订产品？明智的选择是后者。

软件测试员必须要想到产品需求可能改变。未曾计划的特性会增加，经过测试并报告软件缺陷的特性可能发生变化甚至被删除。这些者是可能的。



原始封面

![课程图片](https://images.unsplash.com/photo-1504384308090-c894fdcc538d?w=300)


