综述对软件测试认识的十二大误区(转)

上一篇 / 下一篇  2009-07-23 20:02:29

本文转自:http://bbs.51testing.com/thread-142816-1-1.html                                    作者:阿七

[摘要]

随着大家对于软件质量的重视程度越来越高,导致了测试在软件开发中的地位越来越重要了。没错,测试是目前用来验证软件是否能够完成所期望功能的最有效的方法之一。在这一趋势的引导下,现在很多软件相关的公司都非常重视对于他们所开发的软件的测试,甚至不惜花费巨资购买商用的测试工具,但是效果却不一定理想。究其原因主要是存在着对于软件测试的诸多误区。本文对一些比较普遍的关于测试的误区进行些剖析,并且就测试对于软件产品质量可能带来的更深远的影响方面,也进行些论述。
[关键字]:测试  误区  软件质量  
引子测试在软件开发过程中一直都是备受关注的,即使是在传统的软件工程中,也有一个明确、独立的测试阶段。随着软件危机的频频出现以及人们对于软件本质的进一步认识,测试的地位得到了前所未有的提高。测试已经不仅仅局限于软件开发中的一个阶段,它已经开始贯穿于整个软件开发过程,人们已经开始认识到:测试开始的时间越早,测试执行的越频繁,所带来的整个软件开发成本的下降就会越多。

但是,相对于测试这个词的流行程度而言,有关测试教育方面的工作做的还远远不够,很多关于测试的文章都是针对某种测试工具使用方面的,而测试工具厂商也往往出于商业的目的对于测试工具的作用夸大其词。这样,很多的软件从业者就很容易陷入一些误区,导致了测试并没有在他们所在的软件开发项目中起到有效的作用。下面几点将对于一些比较具有代表性的误区进行剖析,并对于测试背后所蕴含的一些设计思考进行了阐述,希望能够起到抛砖引玉的作用。

误区一: 需求-实现-测试,软件测试是开发后期的一个阶段;

实际上,软件测试贯穿整个软件产品生命期。一方面,软件测试也要经历测试计划、测试用例的设计和实现,以及测试运行一系列的阶段,因此,早在软件需求阶段,甚至更早,软件测试的工作就要开始了。另一方面,软件测试越早进行越好,因为BUG越早发现,BUG造成的影响和修改的代价就越小。而且,软件测试并不仅仅针对程序,软件的需求、设计等等也要被测试。
测试是一个泛型概念(全程测试)。如果单纯的只将程序设计阶段后的阶段称之为软件测试的话,需求阶段和设计阶段的缺陷产生的放大效应会加大。这非常不利于保证软件质量。需求缺陷、设计缺陷同样也是软件缺陷,而且软件缺陷具有生育能力。需求有问题,连带着设计会出问题,最后到测试完成,客户拿到自己不是想要的产品。缺陷不断放大。所以软件测试应该跨越整个软件开发流程。需求验证(自检)和设计验证(自检)也可以算作软件测试(建议称为:需求测试和设计测试)的一种。软件测试应该是一个泛型概念,涵盖整个软件生命周期,这样才能确保周期的每个阶段经得起考验。同时测试本身也需要有第三者进行评估(信息系统审计和软件工程监理),即测试本身也应当被测试,从而确保测试自身的可靠性和高效性。否则自身不正,难以服人。另外还需指出的是软件测试是提高软件产品质量的必要条件而非充分条件,软件测试是提高产品质量最直接、最快捷的手段,但决不是一个根本手段。



误区二:软件测试对技术要求不高,至少比编程容易得多。很多人认为测试就是运行一下软件,然后看看结果对不对就可以了。首先这就是一个对测试缺乏根本的认识。看看结果对不对,可以采取很多方式,白盒测试需要分析代码逻辑来输入特例数据,黑盒测试需要执行常规操作来看反馈是否正确。测试是有目的的发现程序的错误,如果对程序本身不理解,是无法找出程序的不合理的。所以,测试人员不仅知道程序员的代码,还要知道程序员的思维漏洞。
(A) 白盒测试不仅要理顺程序员的思路,还要找出其不合理之处;
(B) 黑盒测试不仅要理解客户的需求,还要找出其暗藏的逻辑不合理性;
(C) 白盒测试相对黑盒测试更具体一些,但正是黑盒测试面对的不确定性、抽象性、逻辑性、变动性、随机性和发散性,从而增加了其自身含金量。
这里要补充的是,软件测试的经验累积也是非常重要的。而且,测试不仅仅只是运行程序,还涉及到测试的管理。而管理能力的扩展,是无限延伸的。

[url=]
误区三:使用测试工具,就是进行了有效的测试[/url]

一个软件开发团队往往认为只要自己使用了某种软件测试工具,那么就应该可以获取测试带来的种种好处,这种想法当然是错误的。因为,要想对一个软件或者模块进行有效的测试,首先该软件或者模块应该是可测试的。可测试性是反映软件质量的一个内在属性,不会因为你使用了某种测试工具进行了测试行为,就使得被测试的软件具有了可测试性。如果被测试的软件本身并不具备可测试性,那么使用多么昂贵的测试工具进行测试所能够带来的收益都是微乎其微的。  
还好,可测试性和好的软件品质的其他方面有天然的关联,一个具有可测试性的软件必然是一个强内聚、弱耦合、接口明确、意图明晰的软件,而不可测试的软件往往具有过强的耦合和混乱的逻辑。关于可测试性方面更多的内容不在本文的论述范围,请自行参见相关的文献。
要想真正获取测试带来的巨大好处,并且使得测试工具能够发挥最大的效率,关键就是要使软件本身具有很好的可测试性。这种能力的获取是一个逐步的过程,是不可能一蹴而就的。最关键的一点就是要不断实践,不断学习一些优秀的经验,不断的反思。要想获取好的结果,就必须要付出努力,这是亘古不变的真理。
对于测试工具的选择,只要满足需要并能够自动运行测试用例就可以了。不要一味的追求复杂的功能和不必要的灵活性。目前没有比较好的满足各方面需要通用的测试工具,不过使用脚本语言,循序渐进的自行开发一个适合自己的验收测试工具也不是一件困难的事情,一句话:只有提高了自身团队内在的素质,外在的工具才能够发挥作用。

误区四: 自动化测试是万能的。


自动化测试可以提高效率,但不可能提高质量。业界的80/20法则同样适用于此,即20%的工作量可以完成80%的自动化工作,其余20%的自动化,需要再投入80%的成本。完全相信自动化测试的人,就好像相信机器人能够取代人类一样。自动化测试存在有以下的缺点:(1)、不能完全取代手工测试
(2)、手工测试比自动测试发现的缺陷更多(3)、对测试质量的依赖性极大(4)、测试自动化不能提高有效性
   (5)、测试自动化可能会制约软件开发。由于自动测试比手动测试更脆弱,所以维护会受到限制,从而制约软件的开发。
   (6)、工具本身并无想像力

误区五:有时间就多测,没有时间就少测。


测试不是可有可无的,测试和客户需求采集,系统分析,编码一样,是必不可少的一个阶段。项目经理必须为测试安排合理的时间,决不可随意分配一些零散时间或者多余时间。让我们从风险的角度给出数据证明:

(1)、假设在分析阶段发现错误后其修正成本是1个货币单位(可以理解为1个月的开发费用,或者3个月的加班加点支出);

(2)、在设计编码阶段发现错误后修正的成本就是65个货币单位;

(3)、在集成测试,系统测试和验收测试时发现错误后其修正成本是15个货币单位;

(4)、在发布之后(已经交付给客户了)的修正成本是60100个货币单位。

所以,测试时间的安排决不可放在最后,决不可随意定量。

[url=]误区六:存在太多的无法测试的东西
[/url]


在软件开发领域,确实存在一些东西看起来要比另外一些东西难测试一些,但是远非无法测试。并且在大多数的情况下,还是由于被测试的软件本身在设计时没有考虑到可测试性的问题。只不过这种不可测试性不是由于被测试的软件内部的过紧耦合造成的,而是和外部某些很难测试的部分耦合过紧,从而表现出被测试的软件本身很难测试。这些很难测试的部分比较常见的有:图形界面、硬件、数据库等。下面以图形界面为例进行说明。

如果一个软件模块必须要通过图形界面才能够触发它的应用逻辑时,那么要对这个软件模块进行测试时就必须要使用图形界面。但是图形界面又是很难测试的。看起来好像很难办。让我们换一个角度考虑一下,其实我们真正想要测试的是软件模块本身的应用逻辑,而不是图形界面的触发逻辑。如果我们在设计时能够把被测试的软件模块本身进行很好的封装,定义良好的服务提供接口,那么我们就完全可以通过软件模块本身提供的接口进行测试。这样就可以绕过难以测试的图形界面。造成上述软件模块很难测试的原因正是由于在设计时把软件模块本身的应用逻辑和图形界面这两个无关的逻辑耦合在了一起。把这两个逻辑分离,不仅可以对该软件模块进行更容易、更有效的测试,而且也使得该软件模块具有了很好的可重用性和可移植性。

那么对于不好测试的图形界面,我们该怎么办呢?原则很简单,如果某种东西不好测试,那么就让它做肯定不会出错的事情,而把可能会出错的逻辑剥离出来,放到一个可以测试的模块中。对于图形界面来说,就是仅仅保持一个很薄的图形界面逻辑,它的工作就是把用户的请求简单的转发给真正处理该请求的软件模块。转发逻辑足够简单以至于它肯定不会出错,所以我们也无需对它进行测试。

如果在进行软件开发时能够首先编写测试代码,那么就会迫使你从易使用性,易测试性的角度开考虑问题,从而你就会专注于软件模块的高层抽象和职责。这样就会定义出清晰的、明确反映意图的模块接口来,另外,为了使得测试能够进行,你就会主动把那些导致不好测试的耦合去掉。这样的结果不仅仅是获得了可测试性,并且也产生了更好的设计和系统架构。
但是确实存在一些不好测试的东西并且很难只让它执行一些非常简单的逻辑,比如嵌入式系统中的BSP(板级支持包)。开发它们所使用的语言、环境以及它们本身的特性等决定了它们是很难测试的。这里说的难测试其实是一个测试代价问题,具体的说就是要付出更多的时间和努力。这就需要你在付出的代价和测试带来的收益之间进行平衡。如果付出的代价所带来的收益(更少的调试、维护、发布成本)是巨大的,那么付出的代价就是非常值得的。

误区七:测试是枯燥无味的,是缺乏创造力的。



这取决于你站在哪个角度看问题。一个好的测试需要经过计划,设计,执行,统计,分析等过程。仅其中一个设计好的测试案例,就需要你发挥无限的想像力。增加测试案例的深度和广度,可以加深测试人员对风险的探测能力,而这正是一个项目经理所需要的能力之一。同样是写自传,有的人可以写成一本百科全书,有的人却只能写出两三页。


误区八:测试只要证明软件正确就可以了。



测试无法证明软件是正确的,测试只能证明软件能够按照既定的规格和标准来执行,测试的目的是为了发现错误,而不是发现所有错误。现实中的用户操作,就是一个个的测试案例,测试人员不可能穷尽这些测试案例,所以会有部分错误只有用户才能发现。这些案例有可能属于非常规操作,但用户只会说软件质量有问题,而不会承认自己是非法操作。所以测试单单证明软件正确是绝对不足够的,测试需要找茬,需要去寻找错误、触发错误。

[url=]误区九:测试代码可以随意写
[/url]


大家肯定知道测试代码是不能随意编写的,并且在编写测试代码时也不是抱着一种随意的态度,但是你编写出来的测试代码以及测试代码运行的情况却表现出了一种随意性和无序性。因为你可能并没有弄清楚测试的真正意图所在。

本人曾经看到过有关验收测试的这样一个案例,验收测试者使用昂贵的商用测试工具对一个具有图形界面的软件进行测试。测试的方法是通过编写测试脚本驱动鼠标在图形界面上随机的点击(当然每一次的点击,都点到了图形界面上可以接收事件的区域),然后等待着被测试软件的崩溃。当然这种测试方法可以作为验收测试的一个方面,但是决不是唯一的一个方面。还有更重要的内容被忽视了。

测试的目的是用来检验软件系统是否满足了需求。所以,你的测试代码一定要明确的表达出这一点来。就那上面的案例来说,如果测试者真正从用户的需求出发,那么他写出来的测试脚本肯定不会是那样的,而因该是每一个测试用例都清晰的刻画了一项用户的需求,然后检验系统是否实现了用户期望的功能。这样的测试才是有明确目的,才是最有效的测试。和把界面逻辑和应用逻辑隔离,采用明确表现用户需求测试用例进行测试相比,上面的测试方法不能不说是随意了一点。

在针对类进行的单元测试中,也经常会看到一些错误的测试方法。很多的测试者往往针对类中的每个特定的实现细节进行测试。类中的特定的实现细节是很容易变化的,在快速的迭代式开发中更是如此。一旦你测试的类中的某个实现细节发生了变化,你原先的测试代码就要进行相应的更改,否则就失去了意义。这种频繁更改的代价是巨大的。类是一种抽象,它反映了更高层面的内聚性,它应该有明确的职责和定义良好的服务接口,它的职责和对外的接口相对于内部的实现细节来说要稳定的多,并且我们要验证的正是这个类是否具备了它的职责。因此,在对类进测试时,我们应该针对类的接口来验证类是否实现了它的职责而不是其他。这样写出来的测试代码要稳定的多,也有效的多。
细想一下,造成容易陷入针对实现细节测试的原因主要是由于先实现了类,然后才去进行测试。如果先实现了类的功能,然后在去对类进行测试,潜意识中就会不由自主的想去验证已经完成的类的某种实现细节。如果能够在编写实际类前,首先编写针对该类的测试代码,情况就会有很大的不同,因为这会迫使你从类的使用者的角度去考虑问题。结果就是会把关注点放在类的易用性上,放在类的职责上面,放在类提供服务的接口上面,而不是某种实现细节。总之,测试代码的编写应该从被测试的对象是否满足需要的层面进行,而不是其他。

url=]误区十:单元测试和验收测试没有什么区别[/url]


我们以经常用来和软件进行类比的建筑为例,首先给大家一个感性的认识。单元测试可以类比为一个建筑的质检人员对建筑进行的检测,他关注的重点是建筑的内部结构、地基、框架以及墙壁是否垂直等。他的检测是要保证建筑的各个部分是正常的、安全的,换句话说,就是要保证施工满足建筑上面的质量标准。验收测试可以类比为建筑的使用者来对建筑进行的检测。首先,他认为这个建筑是满足规定的工程质量的,这是有建筑的质检人员来保证的。使用者关注的重点是住在这个建筑的中的感受。他关心建筑的外观是否美观、各个房间的大小是否合适,窗户的位置是否合适,是否能够满足家庭的需要等。这里,建筑的使用者执行的就是验收测试,他是从用户的角度出发的。建筑的质检人员执行的就是单元测试,他是从构建者的角度出发的。

正是这种角度的不同决定了单元测试和验收测试之间的区别。它们是对系统的不同的方面进行的测试,二者是互相补充的。不管我们在系统的构建中使用了多么聪明的方法,不管我们的系统是多么的灵活,但是首先我们的产品必须是可用的,否则我们所做的就是浪费时间,从这一点上来说验收测试要比单元测试显得更加重要。

还以上一小节给出的案例为例,案例中所使用的测试方法仅仅是从系统是否健壮的角度出发进行的,即使系统从不崩溃也不能证明那是一个可用的系统。因为测试根本就不是从用户使用的角度出发的,测试者本应该和用户一起来编写验收测试。单元测试保证我们把事情作对,而验收测试则保证我们做正确的事情。
关于单元测试和验收测试之间的明确划分,没有一个通用的标准,只有通过自己的不断实践来增加这方面的经验。你进行的有关测试的实践越多,你就会越清晰的感觉到单元测试和验收测试之间的界限所在。下面给出一些指导原则,在你编写测试代码时可能会有帮助。
 (1)、如果一个单元测试要跨越类的边界,那么它可能应该是一个验收测试
 (2)、如果一个单元测试变的非常复杂,那么它可能应该是一个验收测试
 (3)、如果一个单元测试经常要随着用户需求的变化而改变,那么它可能应该是一个验收测试
 (4)、如果一个单元测试比它要测试的代码本身要难以编写,那么它可能应该是一个验收测试

误区十一:测试具有免疫性(软件缺陷免疫性)



软件缺陷与病毒一样具有可怕的免疫性,测试人员对其采用的测试越多,其免疫能力就越强,寻找更多软件缺陷就更加困难。由数学上的概率论我们可以推出这一结论。假设一个50000行的程序中有500个软件缺陷并且这些软件错误分布时均匀的,则每100行可以找到一个软件缺陷。我们假设测试人员用某种方法花在查找软件缺陷的精力为X小时/100行。
照此推算,软件存在500个缺陷时,我们查找一个软件缺陷需要X小时,当软件只存在5个错误时,我们每查找一个软件缺陷需要100X小时。实践证明,实际的测试过程比上面的假设更为苛刻,为此我们必须更换不同的测试方式和测试数据。该例子还说明了在软件测试中采用单一的方法不能高效和完全的针对所有软件缺陷,因此软件测试应该尽可能的多采用多种途径进行测试。

误区十二:如果软件最后出了问题,肯定都是测试的问题。



软件测试是提高质量的手段,但不是保证质量的唯一途径。并不是只要进行了测试,软件质量就一定会得到保证。每个人都必须明确,软件的质量不是测出来的,世界上没有不出错的软件,任何一个测试人员也不可能发现所有的程序错误。有以下多种情况导致额外的错误出现:

(1)、程序代码没有错,但表现出来的界面却是错误的。


(2)、客户需求本身即存在逻辑性错误,但软件项目却必须按照客户的需求进行开发;

(3)、测试是不可以穷尽的;

(4)、不同企业或者不同客户,对错误的容忍程度、依据标准是不同的;

(5)、软件质量的保证需要所有人来负责。举个最简单的例子,有的程序员会在公司项目里留下自己的木马或者后台,在客户的需求里没有此项检查,测试当然发现不了问题。而且问题只有在程序员人品出现问题时才会暴露出来,所以由此可见质量的保证不能全部推卸到测试身上;

(6)、企业给予测试很低的付出和支持,却要求承担极大地责任,管理上的不合理同样会转换到产品的错误上——这与大跃进时代没有区别;

(7)、软件产业的成功不是依赖于软件技术的先进性,而是要求一个规范的软件开发过程,一个全局的质量控制体系。软件测试同样要求如此。建筑行业,无论是最初的泥瓦工加拖车,还是现在的钢筋混凝土,其质量保证体系是基本不变的。





结语



测试是用来保证软件开发过程的高效性,以及保证开发出来的软件产品的高质量和可用性的。软件开发本身就是一件非常困难的事情,这也决定了有效的测试决不是简单的依靠一些测试工具就可以进行的。在使用工具的同时,我们更要加强关于测试的培训、教育,使大家对于测试首先有一个正确的认识。只有这样,我们才能够更加有效、高效的使用工具,才能够使测试真正起到它应有的作用。希望本文能够对大家在进行测试方面的工作存在的误区有所解答,也对以后的测试工作有所帮助。


TAG:

 

评分:0

我来说两句

日历

« 2024-05-07  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 20263
  • 日志数: 40
  • 建立时间: 2009-04-26
  • 更新时间: 2012-10-17

RSS订阅

Open Toolbar