软件测试战略_测试那些事

这几天看了一些关于软件工程里面软件测试方面的书籍,感觉蛮有收获,试与诸君共分享之。


    软件测试,对我这个才进入软件领域两年不到的菜鸟来说是一个既熟悉又陌生的词汇。每个软件行业的人不可能没听说过软件测试,但是,我相信大多数和我一样的菜鸟都没有真正对自己写的软件程序做过系统的测试工作。


说到这里,有很多同学都不乐意了。我怎么没测试了?!!我都是写一段代码就run一下,保证一段代码成功了才写后面的好不好。而且,我写的程序都能正确运行好不好。OK,OK,先不谈这个,当年我也是这么认为的,关于这点我们首先来界定下何为软件测试再说。


官话:软件测试的目的是为了发现软件设计和实现过程中的疏忽说造成的错误。

我的理解:发现并修改软件中不好的部分。这些不好的地方指错误、低效代码、不合理或不方便的设计等等一切影响功能和最终客户反馈的地方。


同学们,还坚持么?


一个很吓人的事实是软件界存在8020法则,即大多数好的软件其测试所花费的工作量比其他所有的软件工程加起来都多,比例为80:20。从这个角度来讲,若大型系统的测试还像小游戏一样无规则、无计划的进行测试,结果可想而知...可想而知,好的测试思路与方法在正式的测试工作当中是绝对必要的了...


一、软件测试的战略方法与思想

1.1 验证与确认(Verification and Validation,V&V)

在大的方向,软件测试通常做两件事:验证--即保证软件的功能正确实现,和确认--确保软件合乎客户真正的需求。

 

上面的话可能让人头痛----不是一样的意思么?

 

好吧,换一种说法:验证--我们在正确的构造产品么? 确认--我们在构造正确的产品么?

 

验证不用说,正确性是软件(其实远不止软件)最基本的要求,做计算器时你至少得保证1+1不等于3吧!!关于确认,很多编程人员都有一个误区,就是我做客户让我做的东西。但一个很重要的问题是,客户提出的需求真的与软件的实际需求一致么?撇去客户表达与需求分析之间的不一致性不谈,在人机设计与界面交互这一块我们能做的更好吧。这里借用MXR同学的成果(见图1):当我们在做webAPP时,对同样的功能需求,不同的表现方式会达到不同的效果。这也就是说,软件测试,不仅仅是测试错误,更要对软件的可用性与适用性做出修正,即保证软件的质量。同样,测试还应该包括性能监控、可行性研究、数据库评测、算法分析等等一切影响软件质量的属性。



图1

 

 

1.2 软件测试的组织

V&V实现解决了测试是干什么这个基本问题,现在要解决另一个基本问题:谁来做测试工作?


很多人会有这样的思想,对同样的东西(这里是指待测试的软件模型),不同的人在认识上肯定会有差异。那么,软件开发人员对软件进行测试是一个很好的选择,谁能比开发者本人更了解程序呢!!!这也是为什么别人列出一长串代码让你找出某个错误时,你不耐烦的原因。


然而,一个显而易见的事实是,开发人员本身总是急于展现他们所开发的程序的正确性,是成功的,是符合期望的,这是人之常情。令人遗憾的是,错误时客观存在的。笔者也经常在向别人展示自己花了很大心思做成的程序时,试图掩饰莫名出现的错误。有人说过,从心理学方面来看,软件的分析和设计都是一类建设性的工作。从本文后面可以看到,软件人员总是努力构造测试实例来“破坏”软件。软件工程师也会自豪与自己的“孩子”,这种仇视任何一个企图伤害自己“孩子”的人这种心理是可以理解的。


那么是否可以得出结论:开发工作与测试工作应该分离开来?答案是否定的。虽然独立测试组(Independent Test Group,ITG)在所有大公司都是存在的,但开发人员与测试人员在软件开发初期就应该进行交流。一个原因前面已经说了,你能忍受从头看别人给你的100000+行代码,然后找出某个似乎存在的错误么?笔者在前一段时间试图分析hadoop的源代码,不到两天脑袋就歇菜了。另一个可能的原因是,测试并不仅仅是“大家一起来找茬”,而是一个自我修正的过程,完全需要开发人员一起来参与。

 

从这个意义上来讲,ITG是软件开发项目组的一部分。

 

 

1.3 软件测试的流程

如图2所示,在软件工程的螺旋开发模型当中,软件开发呈螺旋方式(PS:可能没画出螺旋效果,见谅)。工作开始初期需

要在系统级别定义软件的角色,接着进行需求分析活动,紧接着的是整体与单元设计,最后

则是编码阶段。一步一步降低抽象层次。

 




 
图2

 

软件的测试过程同样可以以一种螺旋模型看待。与开发过程不同,测试过程是一种由内而外的过程,即首先进行单元测试,接着是集成测试,然后是确认测试,最后的活动室系统测试。一般而言,单元测试和集成测试的主要工作在开发期。


单元测试:

单元测试软件设计的最小单元(软件构件或模块)的验证过程。这个过程侧重于构件中的内部处理逻辑与对外接口、局部数据结构、独立路径和错误处理路径。测试内部逻辑与对外接口是为了测试对单元数据的正常流入与流出。这部分不关心数据在构件间的交互。检查数据结构是为了保证数据信息在算法的执行过程中保证其完整性。笔者曾经写了一个二叉决策树,用于一个坦克大战的小游戏程序中AI坦克方向判断,但每次在坦克变换方向后都回到初始地方,后来发现是在算法结束后有一项数据被清零了,囧。独立路径和错误处理路径会在后面介绍测试战术中的白盒测试的文章中提到。

 

下面列出别人总结的一些计算中常见的错误:1)不正确的算术优先级 2)混合模式操作,貌似我也不理解这个 3)不正确的初始化,以前老犯,现在好了些 4)不精确的精度,暂时没碰到过,估计一旦出问题,很难发现 5)表达式有不正确的符号表示 5)边缘测试,这个特别重要,软件在边界出错,通常出现在n维数组或者n次循环的第1个或者第n个元素,哎,这个错误笔者犯的数不胜数了,而且一直改不了

 

     单元测试的另一个比较重要的特点是能并行进行,这通常是由于构件或者模块之间的非相关性造成的。这点在测试中很重要,通常会大大缩短测试时间。

 

为了更好的进行单元测试,软件需要设计的高内聚,也就是设计之初就要采用好的设计模式。这点毫无疑问。

 

集成测试:

以前,我一直想这样一个问题:如果每个模块都是正确的,为什么要担心将它们集成在一起后的结果呢?后来在多次参与团队合作项目之后,终于意识到集成检测(即使这样还是没意识到集成测试,而仅仅是集成检测)的重要性。关键还是“接口”一词。数据在模块之间流动时可能部分丢失甚至更改;在一些设计不好的软件中,或者说不可避免的在所有软件中,模块之间会有影响;全局数据结构等等。而这些问题在多个模块之间很可能会迭代扩大到无法承受的地步。


一个不是很恰当的例子,在TCP/IP协议中,网络层的IP协议与传输层的TCP协议都是设计良好的协议,单独工作都很好,但是集成起来以后必须增加像ICMP这样的辅助协议才能协调工作。


一个更加危险的倾向是,集成的错误常常是非增量式的。也就是说,系统在第一次集成时会报一大堆的错误,这是因为,错误会在构件之间进行传递。而且,一旦改正了某个错误,反而会出现一系列的新的错误,以此类推。


由此可见,集成测试是比单元测试更重要也更复杂的测试过程。为了解决这个问题,计算机界的先辈们(PS:大多数是国外的人,哎)提出了许多富有成效的继承测试策略,比如自顶向下集成测试、自底向下集成测试、回归测试、冒烟测试等等。太麻烦了,我就不浪费版面的(其实是我也讲不太清,囧)。有兴趣的朋友可以google之。

确认测试:

确认测试在前面已经提到过了,是为软件满足完备的功能,行为以及性能,交互需求等提供最后的保证。

 


系统测试:

这最后的一步实际上已经超出了一半编程人员或者说是测试人员的工程范围。我们知道,软件的运行并不只是软件本身的结构,而是与硬件、数据库、操作人员、市场环境共同参与的结果。软件的系统测试必须考虑所有的这些因素,这也是为什么我们说你永远不能完成测试,这个任务只会从软件开发人员转移到客户身上的原因。

 

 

 

1.4 软件测试成功的标准

我想,这是许多关注这篇文章的人最关心的问题之一:测试工作要做到什么时候?


关于这个问题我当初也是很感兴趣,我遍查了很多书籍,也在网上搜了很多牛人对这个问题的回答,可惜,一直没找到一个大众的回答。许多回答都只是经验之谈。

 

一个比较大众的回答是:测试工作不可能完成,最多是这个工作由程序员转移到客户身上。这和峰哥经常强调的“程序没有完成的一天(咆哮语气)!!”观点类似。


另一种回答稍显无聊,但又是非常准确的:一直测试,知道你时间或是资金不能支持为止。

 

 

END!

猜你喜欢

转载自263796001-qq-com.iteye.com/blog/1460705