软件架构之测评方法

第 11 章:测试评审方法

软件测试与评审是软件质量保证的主要手段之一,也是在将软件交付给客户之前所必须完成的步骤。目前,软件的正确性证明尚未得到根本的解决,软件测试与评审仍是发现软件错误(缺陷)的主要手段。

本章重点要求读者掌握测试方法、评审方法、验证与确认、测试自动化、面向对象的测试等 5 个方面的知识。

11.1 测试方法

在介绍软件测试之前,首先应该明确“错误”(error)和“缺陷”(fault)的概念。根据IEEE 的定义,“错误”主要针对软件开发过程,“缺陷”主要针对软件产品。软件开发人员在软件开发过程(主要是分析、设计和编码过程)中所出现的“错误”是导致软件产品“缺陷”的原因,反过来说,“缺陷”是“错误”的结果和表现形式。

软件测试的目的就是在软件投入生产性运行之前,尽可能多地发现软件产品(主要是指程序)中的错误(缺陷)。 为了发现软件中的错误(缺陷),应竭力设计能暴露错误(缺陷)的测试用例。

测试用例是由测试数据和预期结果构成的。一个好的测试用例是极有可能发现至今为止尚未发现的错误(缺陷)的测试用例。一次成功的测试是发现了至今为止尚未发现的错误(缺陷)的测试。

高效的测试是指用少量的测试用例,发现被测软件尽可能多的错误(缺陷)。软件测试所追求的目标就是以尽可能少的时间和人力发现软件产品中尽可能多的错误(缺陷)

11.1.1 软件测试阶段

从测试阶段上分,软件测试通常可分为单元测试、集成测试和系统测试。

1.单元测试
单元测试(unit testing),也称模块测试,通常可放在编程阶段,由程序员对自己编写的模块自行测试,检查模块是否实现了详细设计说明书中规定的功能和算法。单元测试主要发现编程和详细设计中产生的错误,单元测试计划应该在详细设计阶段制定。

单元测试期间着重从以下几个方面对模块进行测试:模块接口、局部数据结构、重要的执行通路、出错处理通路和边界条件等。 测试一个模块时需要为该模块编写一个驱动模块和若干个桩(stub)模块。驱动模块用来调用被测模块,它接收测试者提供的测试数据,并把这些数据传送给被测模块,然后从被测模块接收测试结果,并以某种可以看见的方式(例如显示或打印)将测试结果返回给测试者。桩模块用来模拟被测模块所调用的子模块,它接受被测模块的调用,检验调用参数,并以尽可能简单的操作模拟被调用的子程序模块功能,把结果送回被测模块。顶层模块测试时不需要驱动模块,底层模块测试时不需要桩模块。

模块的内聚程度高可以简化单元测试过程。如果每个模块只完成一种功能,则需要的测试方案数目将明显减少,模块中的错误也更容易预测和发现。

2.集成测试
集成测试(integration testing),也称组装测试,它是对由各模块组装而成的程序进行测试,主要目标是发现模块间的接口和通信问题。例如,数据穿过接口可能丢失,一个模块对另一个模块可能由于疏忽而造成有害影响,把子功能组合起来可能不产生预期的主功能,个别看来是可以接受的误差可能积累到不能接受的程度,全程数据结构可能有问题等。集成测试主要发现设计阶段产生的错误,集成测试计划应该在概要设计阶段制订。

集成的方式可分为非渐增式和渐增式。

  • 非渐增式集成是先测试所有的模块,然后一下子把所有这些模块集成到一起,并把庞大的程序作为一个整体来测试。这种测试方法的出发点是可以“一步到位”,但测试者面对众多的错误现象,往往难以分清哪些是“真正的”错误,哪些是由其他错误引起的“假性错误”,诊断定位和改正错误也十分困难。非渐增式集成只适合一些非常小的软件。
  • 渐增式集成是将单元测试和集成测试合并到一起,它根据模块结构图,按某种次序选一个尚未测试的模块,把它同已经测试好的模块组合在一起进行测试,每次增加一个模块,直到所有模块被集成在程序中。这种测试方法比较容易定位和改正错误,目前在进行集成测试时已普遍采用渐增式集成。

渐增式集成又可分为自顶向下集成和自底向上集成。自顶向下集成先测试上层模块,再测试下层模块。由于测试下层模块时它的上层模块已测试过,所以不必另外编写驱动模块。

自底向上集成先测试下层模块,再测试上层模块。同样,由于测试上层模块时它的下层模块已测试过,所以不必另外编写桩模块。这两种集成方法各有利弊,一种方法的优点恰好对应于另一种方法的缺点,实际测试时可根据软件特点及进度安排灵活选用最适当的方法,也可将两种方法混合使用。

3.系统测试
系统测试是软件测试中的最后的、最完整的测试,它是在单元测试和集成测试的基础上进行的,它从全局来考察软件系统的功能和性能要求。系统测试计划应该在需求分析阶段制订。 通常,系统测试包括确认测试和验收测试。

确认测试,主要依据软件需求说明书检查软件的功能、性能及其他特征是否与用户的需求一致。软件配置复查是确认测试的另一项重要内容。复查的目的是保证软件配置的所有成分都已齐全,质量符合要求,文档与程序完全一致,具有完成软件维护所必需的细节。 如果一个软件是为某个客户定制的,最后还要由该客户来实施验收测试,以便确认其所有需求是否都已得到满足。由于软件系统的复杂性,在实际工作中,验收测试可能会持续到用户实际使用该软件之后的相当长的一段时间。 如果一个软件是作为产品被许多客户使用的,不可能也没必要由每个客户进行验收测试。

绝大多数软件开发商都使用被称为 (Alpha)测试和 (Beta)测试的过程,来发现那些看起来只有最终用户才能发现的错误。

a 测试由用户在开发者的场所进行,并且在开发者的指导下进行测试。开发者负责记录发现的错误和使用中遇到的问题。也就是说, 测试是在“受控的”环境中进行的。
b 测试是在一个或多个用户的现场由该软件的最终用户实施的,开发者通常不在现场,用户负责记录发现的错误和使用中遇到的问题并把这些问题报告给开发者。也就是说,测试是在“不受控的”环境中进行的。经过系统测试之后的软件通常就可以交付使用了。

11.1.2 白盒测试和黑盒测试

从测试方法上分,软件测试可分为白盒测试和黑盒测试。
1.白盒测试
白盒测试,又称结构测试,主要用于单元测试阶段。它的前提是可以把程序看成装在一个透明的白箱子里,测试者完全知道程序的结构和处理算法。这种方法按照程序内部逻辑设计测试用例,检测程序中的主要执行通路是否都能按预定要求正常工作。

白盒测试根据软件的内部逻辑设计测试用例,常用的技术是逻辑覆盖,即考察用测试数据运行被测程序时对程序逻辑的覆盖程度。主要的覆盖标准有 6 种:语句覆盖、判定覆盖、条件覆盖、判定/条件覆盖、组合条件覆盖和路径覆盖。

(1)语句覆盖。语句覆盖是指选择足够多的测试用例,使得运行这些测试用例时,被测程序的每个语句至少执行一次。很显然,语句覆盖是一种很弱的覆盖标准。

(2)判定覆盖。判定覆盖又称分支覆盖,它的含义是,不仅每个语句至少执行一次,而且每个判定的每种可能的结果(分支)都至少执行一次。判定覆盖比语句覆盖强,但对程序逻辑的覆盖程度仍然不高。

(3)条件覆盖。条件覆盖的含义是,不仅每个语句至少执行一次,而且使判定表达式中的每个条件都取得各种可能的结果。条件覆盖不一定包含判定覆盖,判定覆盖也不一定包含条件覆盖。

(4)判定/条件覆盖。同时满足判定覆盖和条件覆盖的逻辑覆盖称为判定/条件覆盖。它的含义是,选取足够的测试用例,使得判定表达式中每个条件的所有可能结果至少出现一次,而且每个判定本身的所有可能结果也至少出现一次。

(5)条件组合覆盖。条件组合覆盖的含义是,选取足够的测试用例,使得每个判定表达式中条件结果的所有可能组合至少出现一次。显然,满足条件组合覆盖的测试用例,也一定满足判定/条件覆盖。因此,条件组合覆盖是上述 5 种覆盖标准中最强的一种。然而,条件组合覆盖还不能保证程序中所有可能的路径都至少经过一次。

(6)路径覆盖。路径覆盖的含义是,选取足够的测试用例,使得程序的每条可能执行到的路径都至少经过一次(如果程序中有环路,则要求每条环路路径至少经过一次)。路径覆盖实际上考虑了程序中各种判定结果的所有可能组合,因此是一种较强的覆盖标准。但路径覆盖并未考虑判定中的条件结果的组合,并不能代替条件覆盖和条件组合覆盖。

2.黑盒测试
黑盒测试,又称功能测试,主要用于集成测试和确认测试阶段。它把软件看作一个不透明的黑箱子,完全不考虑(或不了解)软件的内部结构和处理算法,它只检查软件功能是否能按照软件需求说明书的要求正常使用,软件是否能适当地接收输入数据并产生正确的输出信息,软件运行过程中能否保持外部信息(例如文件和数据库)的完整性等。黑盒测试根据软件需求说明书所规定的功能来设计测试用例,它不考虑软件的内部结构
和处理算法。

常用的黑盒测试技术包括等价类划分、边值分析、错误推测和因果图等。

(1)等价类划分。在设计测试用例时,等价类划分是用得最多的一种黑盒测试方法。
所谓等价类就是某个输入域的集合,对于一个等价类中的输入值来说,它们揭示程序中错误的作用是等效的。也就是说,如果等价类中的一个输入数据能检测出一个错误,那么等价类中的其他输入数据也能检测出同一个错误;反之,如果等价类中的一个输入数据不能检测出某个错误,那么等价类中的其他输入数据也不能检测出这一错误(除非这个等价类的某个子集还属于另一等价类)。

如果一个等价类内的数据是符合(软件需求说明书)要求的、合理的数据,则称这个等价类为有效等价类。有效等价类主要用来检验软件是否实现了软件需求说明书中规定的功能。

如果一个等价类内的数据是不符合(软件需求说明书)要求的、不合理或非法的数据,则称这个等价类为无效等价类。无效等价类主要用来检验软件的容错性。黑盒测试中,利用等价类划分方法设计测试用例的步骤是:

① 根据软件的功能说明,对每一个输入条件确定若干个有效等价类和若干个无效等价类,并为每个有效等价类和无效等价类编号。

② 设计一个测试用例,使其覆盖尽可能多的尚未被覆盖的有效等价类。重复这一步,直至所有的有效等价类均被覆盖。

③ 设计一个测试用例,使其覆盖一个尚未被覆盖的无效等价类。重复这一步,直至所有的无效等价类均被覆盖。

无效等价类是用来测试非正常的输入数据的,因此每个无效等价类都有可能查出软件中的错误,所以要为每个无效等价类设计一个测试用例。

(2)边值分析。经验表明,软件在处理边界情况时最容易出错。设计一些测试用例,使软件恰好运行在边界附近,暴露出软件错误的可能性会更大一些。

通常,每一个等价类的边界,都应该着重测试,选取的测试数据应该恰好等于、稍小于或稍大于边界值。 将等价类划分法和边值分析法结合使用,更有可能发现软件中的错误。

(3)错误推测。使用等价类划分和边值分析技术,有助于设计出具有代表性的、容易暴露软件错误的测试方案。但是,不同类型不同特定的软件通常又有一些特殊的容易出错的地方。错误推测法主要依靠测试人员的经验和直觉,从各种可能的测试方案中选一些最可能引起程序出错的方案。

(4)因果图。因果图法是根据输入条件与输出结果之间的因果关系来设计测试用例的,它首先检查输入条件的各种组合情况,并找出输出结果对输入条件的依赖关系,然后为每种输出条件的组合设计测试用例。

11.1.3 缺陷的分类和级别

根据 IEEE 标准和 Paul C.Jorgensen 的教科书,软件测试中所发现的错误(缺陷)主要包括以下几类:

(1)输入/输出错误。包括不接收正确的输入、接收不正确的输入、描述有错或遗漏、参数有错或遗漏、输出结果有误、输出格式有误、输出时间有误、结果不一致、遗漏结果、不合逻辑的结果、拼写/语法错误、修饰词错误。

(2)逻辑错误。包括遗漏情况、重复情况、极端条件出错、解释有误、遗漏条件、外部条件有错、错误变量的测试、不正确的循环迭代、错误的操作符。

(3)计算错误。包括不正确的算法、遗漏计算、不正确的操作数、不正确的操作、括号错误、精度不够错误的内置函数。

(4)接口错误。包括不正确的中断处理、I/O 时序有错、调用了错误的过程、调用了不存在的过程、参数不匹配、不兼容的类型、过量的包含。

(5)数据错误。包括不正确的初始化、不正确的存储/访问、错误的标识/索引值、不正确的打包/拆包、使用了错误的变量、错误的数据引用、缩放数据范围或单位错误、不正确的数据维数、不正确的下标、不正确的类型、不正确的数据范围、数据超出限制、数据溢出、不一致的数据。根据错误(缺陷)后果的严重程度,Beizer 将错误(缺陷)分为 10 级:

(1)轻微(例如,界面文字有个别的错别字,但不影响理解)。
(2)中等(例如,界面文字错误可能误导操作者)。
(3)使人不悦(例如,数字串被断开)。
(4)影响使用(例如,有些交易没有处理)。
(5)严重(例如,丢失交易)。
(6)非常严重(例如,不正确的交易处理)。
(7)极为严重(例如,经常出现不正确的交易处理)。
(8)无法容忍(例如,数据库遭到破坏)。
(9)灾难性(例如,系统无法工作)。
(10)传染性(例如,可导致其他系统无法工作)

11.1.4 调试

调试又称为排错,调试与成功的测试形影相随。测试成功的标志是发现了错误。根据错误迹象确定错误的原因和准确位置并加以改正,主要依靠排错技术。

调试是一个相当艰苦的过程,究其原因除了开发人员心理方面的障碍外,还因为隐藏在程序中的错误具有下列特殊的性质:

(1)错误的外部征兆远离引起错误的内部原因,对于高度耦合的程序结构此类现象更为严重。
(2)纠正一个错误造成了另一错误现象(暂时)的消失。
(3)某些错误征兆只是假象。
(4)因操作人员一时疏忽造成的某些错误征兆不易追踪。
(5)错误是由于分时而不是程序引起的。
(6)输入条件难以精确地再构造(例如,某些实时应用的输入次序不确定)。
(7)错误征兆时有时无,此现象对嵌入式系统尤其普遍。
(8)错误是由于把任务分布在若干台不同处理机上运行而造成的。

在软件排错过程中,可能遇到大大小小、形形色色的问题,随着问题的增多,排错人员的压力也随之增大,过分的紧张致使开发人员在排除一个问题的同时又引入更多的新问题。

尽管排错不是一门好学的技术,但还是有若干行之有效的方法和策略的,常用的排错策略分为三类:

(1)原始类。原始类排错方法是最常用也是最低效的方法,只有在万般无奈的情况下才使用它,主要思想是“通过计算机找错”。例如输出存储器、寄存器的内容,在程序安排若干输出语句等,凭借大量的现场信息,从中找到出错误的线索。虽然最终也能成功,但难免要耗费大量的时间和精力。

(2)回溯类。回溯法能成功地用于程序的排错。方法是从出现错误征兆处开始,人工地沿控制流程往回追踪,直至发现出错的根源,不幸的是程序变大后,可能的回溯路线显著增加,以致人工进行完全回溯可望而不可即。

(3)排除类。排除法基于归纳和演绎原理,采用“分治”的概念,首先分析与错误出现有关的所有数据,假想一个错误原因,用这些数据证明或反驳它;或者一次列出所有可能的原因,通过测试一一排除。只要某次测试结果说明某种假设已呈现端倪,则立即精化数据,乘胜追击。

11.2 评审方法

根据 IEEE 1028 的定义,评审是对软件元素或者项目状态的一种评估手段,以确定其是否与计划的结果保持一致,并使其得到改进。狭义的“软件评审”通常指软件文档和源程序的评审。广义的“软件评审”还包括与软件测试相结合的评审及管理评审。软件评审包括软件需求评审、概要设计评审、详细设计评审、软件验证和确认评审、功能检查、物理检查、综合检查和管理评审。

(1)软件需求评审。在软件需求分析结束后必须进行软件需求评审( software requirements review),以确保在软件需求说明书中所规定的各项需求的合适性。

(2)概要设计评审。在软件概要设计结束后必须进行概要设计评审(preliminary design review),以评价软件设计说明书中所描述的软件概要设计在总体结构、外部接口、主要部件功能分配、全局数据结构以各主要部件之间的接口等方面的合适性。

(3)详细设计评审。在软件详细设计结束后必须进行详细设计评审(detailed design review),以评价软件设计说明书中所描述的软件详细设计在每一个基本部件的功能、算法和过程描述等方面的合适性。

(4)软件验证和确认评审。在软件验证与确认计划完成后必须进行软件验证与确认评审(software verification and validation review),以评价软件验证与确认计划中所规定的验证与确认方法的合适性与完整性。

(5)功能检查。在软件释放前,要对软件进行功能检查(functional audit),以验证所开发的软件已经满足在软件需求说明书中规定的所有需求。

(6)物理检查。在软件验收前,要对软件进行物理检查(physical audit),以验证程序和文档已经一致并已做好了交付的准备。

(7)综合检查。在软件验收时,要允许用户或用户所委托的专家对所要验收的软件进行设计抽样的综合检查(comprehensive audit),以验证代码和设计文档的一致性、接口规格说明的一致性(硬件和软件)、设计实现和功能需求的一致性、功能需求和测试描述的一致性。

(8)管理评审。要对计划的执行情况定期(或按阶段)进行管理评审(management reviews),这些评审必须由独立于被评审单位的机构或授权的第三方主持进行。在评审过程中,以下几点值得注意:

(1)不应以测试代替评审。许多缺陷是在早期阶段引入的,缺陷发现得越晚,纠正费用越高。而且每个进入下一步骤的缺陷都可能引起下一步骤中的多个缺陷,导致消除成本的剧增。早期阶段可以进行评审,但是无法进行测试,评审的目的就是减少泄漏到测试阶段的缺陷。评审可能会花很多时间,但在测试中节省了时间。而且,测试也不能发现某些特定类型的缺陷(例如违犯编程规范)。

(2)评审人员应关注产品而不应评论开发人员。评审的主要目的是发现产品中的问题,而不是根据产品来评价开发人员的水平。但是往往会出现把产品质量和开发人员水平联系起来的事情,于是评审变了味,变成了“批斗大会”,极大地打击了开发人员的自尊心,以至于严重地影响了评审的效果。

(3)评审人员应关注于实质性问题。评审中经常会出现这样的现象,评审人员过多地关注于一些非实质性的问题,例如,文档的格式、措词,而不是产品的设计。出现这种情况,可能的原因有:没有选择合适的人参加评审,评审人员对评审对象没有足够的了解,无法发现深层次的问题。

(4)评审会议不应变为问题解决方案讨论会。评审会议主要的目的是发现问题,而不是解决问题,问题的解决是评审会议之后需要做的事情。但是,由于开发人员对技术的追求,评审会议往往变成了问题研讨会,大量地占用了评审会议的时间,导致大量评审内容被忽略,留下无数的隐患。

(5)评审应被安排进入项目计划。参与评审需要投入大量的时间和精力,应该被安排进入项目计划中。但在现实中,评审往往变成了临时安排的工作。如此一来,出现评审人员对评审对象不了解的情况也就不足为奇了。

(6)评审参与者应了解整个评审过程。如果评审参与者不了解整个的评审过程,就会有一种自然的抗拒情绪,因为大家看不到做这件事情的效果,感觉很迷茫,这样会严重地影响大家参与评审的积极性。

(7)评审人员事先应对评审材料充分了解。任何一份评审材料都是他人智慧和心血的结晶,需要花足够的时间去了解、熟悉和思考。只有这样,才能在评审会议上发现有价值的深层次问题。在很多的评审中,评审人员因为各种的原因,在评审会议之前对评审材料没有足够的了解,于是出现了评审会议变成了技术报告的怪现象。

(8)应重视评审的组织工作。在组织评审的过程中,很多人不太注意细节。例如,会议时间的设定,会议的通知,会议场所的选择,会场环境的布置,会议设施的提供,会议上气氛的调节和控制等,而实际上这样的细节会大大影响评审会议的效果。

11.3 验证与确认

验证与确认都是确定软件产品是否满足其预期要求和条件的过程。验证可适用于分析、设计、编码、测试和评审等众多的过程,而确认通常用于验收过程。

1.验证
软件项目的验证一般应包括合同验证、过程验证、需求验证、设计验证、编码验证、集成验证和文档验证。
(1)合同验证。应根据下列准则验证合同:

  • 供方具有满足需求的能力。
  • 需求是一致的并覆盖了用户的需要。
  • 为处理需求变更和升级问题规定了适当的规程。
  • 规定了各方之间的接口及其合作规程与范围,包括所有权、许可权、版权和保密要求。
  • 按照需求规定了验收准则和规程。

(2)过程验证。应根据下列准则验证过程:

  • 项目是适当的、及时的。
  • 为项目选择的过程是适当的并满足合同要求的。
  • 用于项目过程的标准、规程和环境是适当的。
  • 根据合同要求为项目配备了经过培训的人员。

(3)需求验证。应根据下列准则验证需求:

  • 需求是明确的、一致的、无歧义的。
  • 需求是可行的。
  • 需求是可测试的。

(4)设计验证。应根据下列准则验证设计:

  • 设计是正确的,是可以实现需求的。
  • 可以从需求导出设计,可以从设计追踪需求。

(5)编码验证。应根据下列准则验证编码:

  • 编码是正确的,可以实现设计和需求。
  • 可以从设计导出编码,可以从编码追踪设计。

(6)集成验证。应根据下列准则验证集成:
每一个软件项的软件部件和软件单元已完整、正确地集成到软件项中。系统的硬件项、软件项和人工操作已完整、正确地集成到系统中。

(7)文档验证。应根据下列准则验证文档:文档是充分的、完备的、一致的。文档制订是及时的。文档配置管理遵循了规定的规程。

2.确认
如果项目需要开展确认工作,应建立一个确认过程,以确认软件产品满足其预期用途。确认可以是组织内部的,也可以由独立的第三方实施。
一般来讲,确认过程应包括下列任务:
(1)编写测试需求、测试用例和测试规程。
(2)确保这些测试需求、测试用例和测试规程可以反映软件产品的预期用途。
(3)执行测试。
(4)确认软件产品满足其预期用途。

11.4 测试自动化

软件测试的工作量很大,但测试却极有可能应用计算机进行相当一部分自动化的工作,原因是测试的许多操作是重复性的、非智力创造性的、需要细致注意力的工作,而计算机就最适合于代替人类去完成这些任务。测试自动化会对整个开发工作的质量、成本和周期带来非常明显的效果。 一些适于考虑进行自动化的测试工作为:

(1)测试用例的生成(包括测试输入、标准输出、测试操作指令等)。

(2)测试的执行控制(包括单机与网络多机分布运行、夜间及假日运行、测试用例调用控制、测试对象、范围、版本控制等)。

(3)测试结果与标准输出的对比。

(4)不吻合的测试结果的分析、记录、分类和通报。

(5)总测试状况的统计,报表的产生。测试自动化与软件配置管理是密不可分的,与测试有关的资源都应在配置管理中统一考虑。

11.5 面向对象的测试

传统的软件测试策略是从“小型测试”开始,逐步走向“大型测试”。即从单元测试开始,然后进入集成测试,最后是系统测试。 面向对象程序的结构不再是传统的功能模块结构,作为一个整体,原有集成测试所要求的逐步地将开发的模块搭建在一起进行测试的方法已成为不可能。而且,面向对象软件抛弃了传统的开发模式,对每个开发阶段都有不同以往的要求和结果,已经不可能用功能细化的观点来检测面向对象分析和设计的结果。因此,传统的测试模型对面向对象软件已经不再适用。

1.面向对象测试模型
面向对象的开发模型突破了传统的瀑布模型,将开发分为 OOA、OOD 和 OOP 三个阶段。针对这种开发模型,结合传统的测试步骤的划分,可以把面向对象的软件测试分为:面向对象分析的测试、面向对象设计的测试、面向对象编程的测试、面向对象的单元测试、面向对象的集成测试和面向对象的系统测试。

2.面向对象分析的测试
传统的面向过程分析是一个功能分解的过程,是把一个系统看成可以分解的功能的集合。功能分解分析法的着眼点在于一个系统需要什么样的信息处理方法和过程,以过程的抽象来对待系统的需要。而面向对象的分析直接映射问题空间,将问题空间中的实例抽象为对象,用对象的结构反映问题空间的复杂实例和复杂关系,用属性和操作表示实例的特性和行为。

OOA 的结果是为后面阶段类的选定和实现、类层次结构的组织和实现提供平台。因此,对OOA 的测试,应从以下方面考虑:
(1)对认定的对象的测试。
(2)对认定的结构的测试。
(3)对认定的主题的测试。
(4)对定义的属性和实例关联的测试。
(5)对定义的服务和消息关联的测试。

3.面向对象设计的测试
传统的结构化设计方法,采用面向作业的思路,它把系统分解以后,提出一组作业,这些作业是以过程实现系统的基础构造,把问题域的分析转化为求解域的设计,分析的结果是设计阶段的输入。而 OOD 以 OOA 为基础归纳出类,并建立类结构或进一步构造成类库,实现分析结果对问题空间的抽象。由此可见,OOD 不是 OOA 的另一思维方式,而是 OOA 的进一步细化和更高层的抽象,OOD 与 OOA 的界限通常是难以严格区分的。

OOD 确定类和类结构不仅是满足当前需求分析的要求,更重要的是通过重新组合或加以适当的补充,能够方便地实现功能的重用和扩充,以不断适应用户的要求。因此,对 OOD 的测试,应从如下三方面考虑:
(1)对认定的类的测试。
(2)对构造的类层次结构的测试。
(3)对类库的支持的测试。

4.面向对象编程的测试
典型的面向对象程序具有继承、封装和多态的新特性,这使得传统的测试策略必须有所改变。封装是对数据的隐藏,外界只能通过被提供的操作来访问或修改数据,这样降低了数据被任意修改和读写的可能性,降低了传统程序中对数据非法操作的测试。继承是面向对象程序的重要特点,继承使得代码的重用性提高,同时也使错误传播的概率提高。多态使得面向对象程序对外呈现出强大的处理能力,但同时却使得程序内 “同一”函数的行为复杂化,测试时不得不考虑对于不同类型参数具体执行的代码和产生的行为。

面向对象程序是把功能的实现分布在类中。能正确实现功能的类,通过消息传递来协同实现设计要求的功能。因此,在 OOP 阶段,忽略类功能实现的细则,将测试的焦点集中在类功能的实现和相应的面向对象程序风格,主要体现为以下两个方面。
(1)数据成员是否满足数据封装的要求。
(2)类是否实现了要求的功能。

5.面向对象的单元测试
传统的单元测试的对象是软件设计的最小单位——模块,测试依据是详细设计说明书。单元测试应对模块内所有重要的控制路径设计测试用例,以便发现模块内部的错误。单元测试多采用白盒测试技术,系统内多个模块可以并行地进行测试。

对于面向对象的软件,单元的概念发生了变化。每个类和类的实例(对象)封装了属性(数据)和操纵这些数据的操作,而不是个体的模块,最小的可测试单位变成了封装的类或对象。因此,单元测试的意义发生了较大变化。不再孤立地测试单个操作,而是将操作作为类的一部分。

6.面向对象的集成测试
传统的集成测试,有两种典型的集成策略:
(1)自顶向下集成,它从主控模块开始,按照软件的控制层次结构,以深度优先或广度优先的策略,逐步把各个模块集成在一起。

(2)自底向上集成,从“原子”模块(即软件结构最低层的模块)开始组装测试。面向对象的软件没有层次控制结构,传统的自顶向下和自底向上集成策略已无太大意义。

此外,一次集成一个操作到类中(传统的增量集成方法)通常是不可能的。对 OO 软件的集成测试也有两种不同策略:第一种称为基于线程的测试,集成系统的一个输入或事件所需的一组类,每个线程被集成并分别测试,并使用回归测试以保证没有产生副作用。第二种称为基于使用的测试,首先测试那些几乎不使用其他类的类(称为独立类)并开始构造系统,在独立类测试完成后,下一层的使用独立类的类(称为依赖类)被测试。这个依赖类层次的测试序列一直持续到构造完整个系统。

7.面向对象的系统测试
通过单元测试和集成测试,仅能保证软件开发的功能得以实现。但不能确认在实际运行时,它是否满足用户的需要。为此,对完成开发的软件必须经过规范的系统测试。系统测试应该尽量搭建与用户实际使用环境相同的测试平台,应该保证被测系统的完整性,对临时没有的系统设备部件,也应有相应的模拟手段。系统测试时,应该参考 OOA 分析的结果,对应描述的对象、属性和各种服务,检测软件是否能够完全“再现”问题空间。系统测试不仅是检测软件的整体行为表现,从另一个侧面看,也是对软件开发设计的再确认。

面向对象测试的整体目标是以最小的工作量发现最多的错误,与传统软件测试的目标是一致的,但 OO 测试的策略与传统测试有很大不同。这种不同主要体现在两个方面,第一,测试的焦点从过程构件(模块)移向了类;第二,测试的视角扩大到了分析和设计模型。

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 01:58:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 01:58:03       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 01:58:03       58 阅读
  4. Python语言-面向对象

    2024-07-12 01:58:03       69 阅读

热门阅读

  1. Webpack打包生产环境进行优化处理

    2024-07-12 01:58:03       20 阅读
  2. 【深度学习】关于模型加速

    2024-07-12 01:58:03       23 阅读
  3. k8s 部署RuoYi-Vue-Plus之mysql搭建

    2024-07-12 01:58:03       23 阅读
  4. 大数据面试题之Hudi(1)

    2024-07-12 01:58:03       18 阅读
  5. ES6 Iterator 与 for...of 循环(五)

    2024-07-12 01:58:03       23 阅读
  6. 对素数的一种新理解

    2024-07-12 01:58:03       22 阅读
  7. 力扣 454四数相加

    2024-07-12 01:58:03       21 阅读
  8. 十大排序算法(慢慢更新)

    2024-07-12 01:58:03       22 阅读
  9. 简谈设计模式之建造者模式

    2024-07-12 01:58:03       18 阅读
  10. 力扣题解(乘积最大子数组)

    2024-07-12 01:58:03       23 阅读
  11. synchronized (userAccount.intern())知识点

    2024-07-12 01:58:03       23 阅读
  12. 网络协议与标准

    2024-07-12 01:58:03       24 阅读
  13. Haproxy搭建Web群集

    2024-07-12 01:58:03       23 阅读