软件测试策略和调试

1               软件测试策略

1.1         软件测试策略概述

测试活动需要采用各种不同的策略。这些策略表明了为确保软件质量而采用了不同的出发点、不同的事例、不同手段和测试方案。我们通常用的较多的方法有:静态方法和动态方法单元测试,集成测试,确认和系统测试;下面的重点将介绍各种测试方法的应用。

1.2       单元测试策略

1.2.1       什么是单元测试?

单元测试是对软件基本组成单元进行测试,这里的基本单元不一定是指一个具体的函数(FunctionProcedure)或一个类的方法,“单元”具有一些基本属性,如:明确的功能、规格定义,明确的接口定义,可清晰地与同一程序的其它单元划分开来。

在纯C语言的代码中,为了操作方便期间,我们一般认为一个函数就是一个单元。

1.2.2             单元测试的主要目的

1. 验证代码是与设计符合的

2. 跟踪需求和设计的实现

3. 发现设计和需求中存在的错误

4. 发现在编码过程中引入的错误

1.2.3             何时开展单元测试

一般地,在编码阶段就应开展单元测试,边写程序边测试是一个好习惯。一个组织不要孤立的划分出编码和单元测试两个阶段,也不要等代码都写完了才开始单元测试。

有时候需要将单元测试时间推后到集成阶段,甚至系统完成阶段。

单元测试可以分为计划、设计、实现、执行几个阶段。“计划”是作好人和时间的安排。“设计”确定采用什么样的测试方法,达到一个什么样的覆盖率标准等。“实现”是设计生成各个测试用例。“执行”包括驱动和桩函数的设计实现,测试数据准备,测试结果验证等等。

1.2.4             单元测试所遵循的原则

对于测试来说,我们应当尽早地和不断地进行软件测试。对于单元测试来说我们需要遵循一定的单元测试规范,根据公司CMM规范中的规定,我们列出了一些原则但是这些并不是足够的。

1.                  仅对全新的代码或修改过的代码进行单元测试

2.                  被测试的对象为实现一组相关功能的代码(一个或一组函数)

3.                  单元测试根据单元测试方案进行,排除测试的随意性

4.                  项目管理者保证测试用例经过审核

5.                  当测试用例的测试结果与预期结果不一致时,单元测试的执行人员需记录实际的测试结果

6.                  对被测试单元需达到的一定的代码覆盖率要求

7.                  当程序进行了修改,由测试执行人员执行回归测试以保证对发现错误的修改没有引入新的错误

 

测试技术组总结的《单元测试过程与结果验收指导书》在这方面给出了比较详细的说明,大家有时间可以看一下。

在做单元测试的时候有时会遇到这样一种现象:既设计人员在设计测试用例的时候或者在调试测试脚本的时候发现了详细设计或者代码中错误,并且改正了这些错误。因此在单元测试用例最后执行的时候发现的问题变少了。这不能表示单元测试的效果变差了。因为在单元测试过程中,通过单元测试方法发现的问题也是属于单元测试发现的问题。单元测试发现的问题不能局限于单元测试用例执行时发现的问题。

仅考虑被测单元的语句覆盖率并不是足够的。语句覆盖100%这是公司硬性的规定,但是不是除此以外我们就不需要兼顾其他覆盖率了呢?不是!有很多错误不是通过达到一定的语句覆盖就能发现的。我们还必须考虑一定的判定覆盖,条件覆盖甚至路径覆盖。一般来说要完全达到路径覆盖几乎是不可能的。但是我们可以考虑McCabe提出的圈路径或Z路径覆盖情况。

同时单元测试不仅仅是作为无错编码一种辅助手段在一次性的开发过程中使用  单元测试必须是可重复的 无论是在软件修改, 或是移植到新的运行环境的过程中。 因此, 所有的测试都必须在整个软件系统的生命周期中进行维护。

VV测试中有一个致命的弱点,也就是它把测试的阶段划分的太明显。其实在实际开发过程中你无法在时间点上严格的结束任何一种测试,因此说单元测试什么时候结束是没有意义的,如果一定要划分,我们可以认为我们的工作重点有单元测试进入另一种测试的标准。

 

1.2.5             正规检视和代码走读

一般在单元测试期间,我们会同步启动一些测试活动,例如代码走读,正规检视,以进一步保证代码质量。

正规检视和代码走读属于同行评审中的两中评审类型,正规检视有严格的流程和纪律,发现错误的效率比较高,但工作量很大,一般一次正规检视的代码量不要超过500行代码。正规检视参与的人员来自于不同领域的人,可以从各个不同的角度去发现代码或文档中深层次的错误。

走读相对来说是比较自由的,没有严格的流程,参与人员一般都是来自于同项目组的人。走读的工作量相对来说是比较小的,一般用于寻找一些浅显的错误。同时走读也作为一种技术交流或理解代码和文档的手段。

单元测试的工作量介于走读和正规检视之间,单元测试是由开发人员完成的,通过设计测试用例来寻找代码中存在的错误。测试用例设计的好坏直接影响单元测试的结果单元测试比较正规检视和走读的最大不同是单元测试可以通过代码的运行来发现错误,而这是正规检视和走读做不到的。单元测试不可缺少,因为有很多错误只有在运行时才能发现得了。

在代码进行单元测试之前应当先进行代码走读和正规检视,它们的侧重点不同。CMM过程规范要求至少40%的代码必须经过正规检视。 单元测试的代码+走读的代码+正规检视的代码 >= 总的代码。

&  总结:

单元测试是一种白盒测试

 

有数据显示,进行适当的单元测试可以发现一个程序中多达70%的缺陷。因此,越早启动单元测试,效果越好。

正规检视、代码走读和单元测试一起进行,可以起到良好的效果。

1.3       集成测试策略

集成测试策略就是在测试对象分析的基础上,描述软件模块集成(组装)的方式、方法。

集成测试的基本策略比较多,分类比较杂,一般来说,可以按测试过程中组合模块的方式,分为增式、非增式和衍变式集成等策略。

    (1) 非增式集成方式: 也称整体组装. 首先对每个模块分别进行模块测试,然后再把所有模块组装在一起进行测试,最终得到要求的软件系统.

    (2) 增殖式集成方式: 也称渐增式组装. 首先对一个个模块进行单元测试,然后将这些模块逐步组装成较大的系统,在组装的过程中, 边连接边测试,以发现连接过程中产生的问题,最后通过增殖逐步组装成为要求的软件系统. 增殖式集成方式有三种实现方式: 自顶向下的增殖方式, 自底向上的增殖方式和混合增殖方式.

   3)衍变式集成方式:结合非增式集成方式和增殖式集成方式,包括,衍变的自顶向下的增殖测试,自底向上-自顶向下的增殖测试等。

&  总结:

集成测试关注的是模块间接口的正确性。

选择良好的集成方式能减少大量的测试工作量。

1.4       验证和确认测试(Verfication and Validation

在广义上,软件测试是验证和确认VERFICATION AND VALIDATION VV〕。验证指保证软件正确地实现了一特定功能的一系列活动。确认是指保证所生产的软件可追溯到用户需求的一系列活动。BOEHMVV的解释是:

VEIFICATION:“Are we building the product right?"

VALIDATION:    " Are we building the right product?"

V&V的定义包含了许多活动,即软件质量保证SQA。图2-1 示出实现软件质量的这些活动。

 

1.4.1             确认测试(Validation Testing)

确认测试又称为效性测试。它的任务是验证软件的功能

和性能及其特性是否与用户的要求一致。对软件的功能和性能要求在软件需求规格说明中已经明确规定。在软件需求规格说明中描述了全部用户可见的软件属性,其中有一节叫做有效性准则,它包含的信息就是软件确认测试的基础。集成测试完成以后,分散开发的模块被联接起来,构成完整的程序。其中各模块之间接口存在的种种问题都已消除。于是测试工作进入最后阶段--确认测试(Validation testing)什么是确认测试,说法众多,其中最简明、最严格的解释是检验所开发的软件是否能按顾客提出的要求运行。若能达到这一要求,则认为开发的软件是合格的。因而有的软件开发部门把确认测试称为合格性测试(qualification testing)。这里所说的顾客要求通常指的是在软件规格说明书中确定的软件功能和技术指标,或是专门为测试所规定的确认准则。

 

1.5       系统测试策略

由于软件只是计算机系统中的一个组成部分,软件开发完成以后,最终还要与系统中其它部分配套运行。系统在投入运行以前各部分需完成组装和确认测试,以保证各组成部分不仅能单独地受到检验,而且在系统各部分协调工作的环境下也能正常工作。这里所说的系统组成部分除去软件外,还可能包括计算机硬件及其相关的外围设备、数据及其收集和传输机构、掌握计算机系统运行的人员及其操作等,甚至还可能包括受计算控制的执行机构。显然,系统的确认测试已经完全超出了软件工作的范围。然而,软件在系统中毕竟占有相当重要的位置,软件的质量如何,软件的测试工作进行得是否扎实势必与能否顺利、成功地完成系统测试关系极大。另一方面,系统测试实际上是针对系统中各个组成部分进行的综合性检验。尽管每一个检验有着特定的目标,然而所有的检测工作都要验证系统中每个部分均已得到正确的集成,并能完成指定的功能。以下分别简要说明几种系统测试:

1.5.1             功能测试(Function Test

功能测试是系统测试中的一种重要测试方法,它不管软件内部的实现逻辑,以检验输入输出信息是否符合规格说明书和需求文档中有关功能需求的规定为目标。 功能测试主要是为了发现以下几类错误:

1、是否有不正确或遗漏了的功能?

2、功能实现是否满足用户需求和系统设计的隐藏需求?

3、输入能否正确接受?能否正确输出结果?

这要求测试设计者对产品的规格说明、需求文档、产品业务功能都非常熟悉,同时对测试用例的设计方法也有一定掌握,才能设计出好的测试方案和测试用例,高效地进行功能测试。

功能测试分为功能测试用例设计,用例执行,输出测试报告等。功能测试的关键在于设计高质量的用例,但用例的设计通常和业务紧密相关,很难给出一般有实际意义的操作指导,但一些方法是共通的。例如:等价类划分,边界值分析,错误推测等。

1.5.2             恢复测试

恢复测试是要采取各种人工干预方式使软件出错,而不能正常工作,进而检验系统的恢复能力。如果系统本身能够自动地进行恢复,则应检验:重新初始化,检验点设置机构、数据恢复以及重新启动是否正确。如果这一恢复需要人为干预,则应考虑平均修复时间是否在限定的范围以内。

1.5.3             安全测试

安全测试的目的在于验证安装在系统内的保护机构确定能够对系统进行保护,使之不受各种非常的干扰。系统的安全测试要设置一些测试用例谋略实在系统的安全保密措施,检验系统是否有安全保密的漏洞。

安全测试要考虑:

l         设备本身的安全性,当受到恶意攻击时,设备的自我保护能力,病毒防护能力,自定义通信协议安全性。
l         物理特性安全性测试(如接地,静电等),
l         业务的安全性测试(如200业务密码验证,201业务密码验证)
l         信息安全性测试。

1.5.4             压力测试

检验系统的能力最高实际限度。进行强度测试时,让系统的运行处于资源的异常数量、异常频率和异常批量的条件下。例如,如果正常的中断平均频率为每秒一到二次,强度测试设计为每秒10次中断。又如某系统正常运行 可支持10个终端并行工作,强度测试则检验15个终端并行工作的情况。

1.5.5             兼容性测试

兼容性测试主要是测试被测试设备于其它设备之间的互连互通性,以及本套产品中各部分之间的相互操作性。

以交换机为例,需要和与其它公司的交换机进行对接测试,包括但不限于:S12405ESS、富士通、NEC以及中兴、大唐、巨龙等公司的交换机。对于本公司的不同型号的交换机也需要进行对接测试,比如需要和无线的MSC、接入网的HONET进行对接测试。

兼容性测试的指导思想是尽可能多地和各种主流设备对接。因此应尽早规划测试方案,收集各种设备。

1.5.6             协议测试

为了使得各网络设备成功地进行通信,必须遵守一组规则。协议(Protocol)规定了一个网络设备在和其它网络设备进行通信时应遵守的规则集合。为了使得来自不同厂家的系统能够成功地进行通信,必须有标准化的协议。这种需求导致了OSI参考模型的制定。但是,描述一组协议并对其标准化并不能确保成功的通信。这是因为协议标准目前基本上是使用自然语言描述的,实现者对于协议的不同理解会导致不同的协议实现,有时甚至会是错误的实现。因此,我们需要一种有效方法对协议实现进行判别,这种方法便是“协议测试”(Protocol Testing)。

1.5.7             可安装性测试

系统的可(重复)安装性测试设计,主要是根据软件的测试特性列表、软件安装、配置文档,设计安装过程的测试用例,发现软件在安装过程中的错误。

系统可安装性测试的目的不是找软件错误,而是找安装错误。在安装软件系统时,会有多种选择。要分配和装入文件与程序,布置适当的配置,进行程序的联结。而安装测试就要找出这些安装过程中出现的错误。

1.5.8             性能测试(Performance Test)和负荷测试(Load Test)策略

性能测试关心的系统的各种指标。例如呼叫的接续时长,系统重起的时间等。这些指标通常需要在一定的话务量背景下进行测量。所以性能测试通常和负荷测试放在一起进行。

负荷测试是以话务模型为基础,通过话务量模拟工具,模拟现网的话务状态,测试系统在高负荷下的反应。负荷测试中常用的术语有:话务量,爱尔兰(Erl),忙时话务量,业务模型,组网模型等。

由于负荷测试的定位问题难度比较大,而且测试成本很高,测试时间也要求较长,所以负荷测试需要在产品计划阶段就着手准备,包括制定测试方案,选择话务模型和重点用例,选择相应的模拟工具,设计调试代码等。

&  总结:

系统测试的方法较多,每种方法均有它的局限性。

只有综合使用各种方法,系统测试才能有效地发现系统缺陷。

2               调试

2.1               调试的定义

调试即排错(debug)。测试的目的是发现问题;问题发现后还需要进一步诊断和改正程序中的错误,而诊断和修正错误的过程就是调试。

调试(排错)是软件开发中必不可少的一个步骤,同时与测试有着密不可分的关系。测试中发现的错误,要经过调试(排错)消除;调试(排错)后的程序还必须再测试,若发现错误则还需要再进行排错调试。测试和调试是交互循环进行(从一个时间段来看是并行进行)的工作

测试需要为调试(排错)提供必要的诊断信息。调试首先是针对具体问题开始的,因此测试发现的问题需要包括出错的现象、具体操作、运作环境、触发条件等等,所有这些可以汇总为“错误征兆”。而错误征兆正是调试(排错)的入口条件。

调试与测试有着明显的区别:

对象不同:

目的不同:测试是发现错误;调试是改正/修正错误。

方法不同:调试工作根据不同的对象、错误相同。

过程不同:测试活动是有序、可重复的活动,有较完备的工程方法支撑;调试则是不可重复的活动,针对具体问题/具体源程序不具备重复性。

&  总结:

测试是发现问题;调试是修正、解决问题。

测试与调试是软件开发过程中密不可分的两个步骤,实际中交互循环进行。

测试与调试在对象、目的、方法、过程有明确的不同和区分。

 

2.2               调试的步骤 definition of debug

调试可以简单分为调试准备、调试两个步骤。

2.2.1             调试准备

一方面调试人员要熟悉程序以及程序运行环境;

更重要的使在程序设计过程中为调试做好准备。

2.2.2             调试

调试一般分为两个步骤:发现/找出错误所在的模块/接口/编码位置;修正/规避错误。其中第一个步骤一般大致占用调试工作量的90%以上。

1.     错误定位

错误定位是调试的第一个步骤。发现错误后首先要根据错误现象、错误症状(同时也称为错误征兆)利用各种调试技术、调试工具/平台结合各种调试方案来分析、定位分析,找出问题原因所在。

2.     错误修正

错误原因位置确定后,下一阶段的工作则是针对错误原因、错误地点进行修正,使问题得到解决。

考虑到实际问题原因的复杂性,实际工作中一个暴露问题的原因可能使多种因素共同作用的结果,即导致问题的原因可能不止一种;同时也有可能前期错误定位的原因/位置判断有误,导致错误修正后问题不能解决或者导致新问题。

实际工作中错误定位和错误修正是相互结合的一个过程;针对每一次修正后的被测对象都要进行相应测试验证;通过测试验证确保问题已经得到解决并不会带来新问题。

&  总结:

调试过程分为调试准备、调试两个阶段。

调试分为错误定位、错误修正两个步骤;其中错误定位的工作量约占调试总工作量的90%以上。

 

2.3               调试策略

调试一般采用逐步排除可能出错原因的思路:即根据问题征兆列出错误所有可能的原因,逐个排除,最后找出真正的问题所在。针对错误可能原因的判断和排错方法形成了不同的调试策略,具体工作中可能采用的调试策略大致包含如下几类:

2.3.1             试探法

调试人员(一般是程序开发人员)分析错误征兆,根据错误表现初步分析、猜想故障的大致位置,然后重点针对错误地点源代码进行代码检视、或者利用前述几种调试技术,逐步定位问题。这种方法比较依赖于程序员对程序的理解、熟悉程度以及问题原因的复杂程度,对于比较复杂的问题这种方法效果比较差,该种测试策略也通常是缓慢而低下的。

2.3.2             回溯法

回溯法是在小程序中常用的非常有效的纠错方法。回溯法

调试人员检查错误现象及征兆,确定最先发现“错误症状”的地方,然后人工回溯源程序代码,沿程序的控制流往后(反方向)回溯跟踪,直到征兆消失处为止;然后在相关邻接的代码段进行查找和分析,找出错误原因。

回溯法对于小程序或者简单问题是一种比较有效的调试策略;但是随着程序规模扩大、逻辑复杂度增加以及问题复杂度增加,回溯法在问题定位中变得几乎不可能。

2.3.3             对分查找法

如果已经明确每个变量再程序内若干个关键点的正确值,则可以用赋值语句或输入语句在程序中间点附近“注入”这些变量的正确值,然后执行程序、检查程序的输出。如果输出结果是正确的,则故障在程序的前半部分;反之,程序在故障的后半部分。对于程序有故障的部分再重复使用这个方法,直到把故障范围缩小到容易判断的程度为止。

2.3.4             归纳法

归纳法是一种系统化的思考方法。所谓规范法就是从特殊推断厨一般的方法,根据错误征兆着手,分析它们之间的关系,进一步分析、判断、查找出错误所在。

归纳法普通可以分为四个步骤:

1.     收集相关数据

列出已经知道的关需程序正确完成的以及错误错误完成的一切数据。这里面对于不产生错误数据但与错误操作类似的一些数据往往能够补充宝贵的线索。

2.     组织数据

整理现有数据以便发现规律。重要的是发现矛盾,即什么条件下出现错误,什么条件下不出现错误。

3.     导出建设

分析研究线索之间的关系,试图找出他们的规律,从而提出关于故障的一个或多个建设。这里如果不能作出推测,则应该设计并执行更多的测试用例,以便获得更多的测试数据支撑分析和假设。如果作出了多种假设,则首先选用其中可能性最大的假设进入下一步工作。

4.     证明假设

利用假设解释原始的所有测试结果,如果能够完全解释一切测试数据,则假设得到证实;否则要么是假设不成立或者不完备,要么是有多个故障同时存在。

2.3.5             演绎法

演绎法类似归纳法的反过程。其思路是从一般原理或前提出发,运用排除和推理过程作出结论。具体做法种演绎法首先列出所有可能的原因和建设,然后划去一个又一个的特殊原因,直到留下一个主要错误原因位置。其基本过程大致包含如下四个步骤:

1.     列举可能的错误原因和假设

根据所有数据,设想所有可能产生错误的原因。不同于归纳法的是,这里并不需要利用这些假设解释各种测试数据。

2.     使用已有数据排除不正确的假设

仔细分析现有数据,寻求其中的关联和矛盾,力求排除前一步列出的各种原因。如果所有列出的假设都被排除了,则需要重新审视/提出新假设或者补充更多的测试数据以提出新的假设;如果余下的假设多余一个,则首先选用可能性最大的一个进入下一步骤。

3.     进一步完善留下的假设

利用已经的测试数据、错误征兆进一步精化余下的假设,使假设更加具体,方便精确确定故障位置。

4.     证明余下假设的正确性

同归纳法第四步;利用假设解释所有原始数据以证明假设。

&  总结:

调试策略的选择对于调试的效果较采用何种调试技术更为重要。

一般的调试策略包括试探法、回溯法、对分查找法、归纳法、演绎法等几种。

归纳法和演绎法是更普遍、相对有效的调试策略。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值