白盒测试
白盒测试又称结构测试、逻辑驱动测试或基于程序的测试,是软件测试的一种重要方法。根据软件产品的内部工作过程,它在计算机上进行测试,以确认每个内部操作是否符合设计规范,以及是否所有内部组件都已检查完毕。其目的是发现程序编码过程中的错误。
白盒测试从测试重点可以分为控制流分析技术和数据流分析技术。从是否执行程序的角度来看,可以分为静态测试方法和动态测试方法。静态测试方法主要是程序结构分析,可分为代码走查、代码审查、控制流分析、数据流分析、信息流分析等。动态测试方法主要分为逻辑覆盖法和路径测试法,其中路径测试法应用最为广泛。
白盒测试的静态测试工具主要包括Logiscope、PRQA软件,动态测试工具主要包括DevPartner软件和Pure series,可以帮助软件测试人员增加代码覆盖率、提高代码质量并发现代码中隐藏的问题。
基本概念
白盒测试基于对产品内部工作的了解,测试用于检查产品的内部动作是否按照规范的规定进行。无论系统的功能如何,它都根据程序的内部结构对程序进行测试,以检查每个程序是否能按照预定的要求正常工作。它通常用于分析程序的内部结构。程序的结构和处理像白盒一样透明,允许测试人员使用程序的内部逻辑结构和相关信息来设计或选择测试用例并测试程序的所有逻辑路径。白盒测试主要用于单元测试和集成测试,但通常不适用于系统测试。但在涉及动态描述的系统描述部分,仍可借鉴一些白盒测试方法。因此,白盒测试不限于单元测试和集成测试。
宗旨原则
白盒测试的主要目的是检查程序模块,在检查过程中应遵循以下原则:
确保程序模块的所有独立执行路径至少测试一次;
在取“真”和“假”的两种情况下,所有逻辑判断都可以至少测试一次;
在上下限和操作范围内运行所有循环;
检查程序的内部数据结构以确保其结构的有效性。
测试方法
动态测试是在程序运行状态下进行的测试,即通过输入预先设计的数据,根据程序运行计算的结果将其与实际输出结果进行比较,然后发现程序中的错误。在程序运行过程中,通过动态测试,测试人员可以判断基本模块、执行过程、子系统以及整个系统的运行结果是否存在缺陷。动态测试方法分为三个步骤。首先设置待测配置,然后对相关源程序进行插桩、编译和链接生成可执行文件,最后插桩程序系统自动记录执行路径并获得覆盖率。动态测试方法分为逻辑覆盖法和路径测试法,其中路径测试法应用最为广泛。
逻辑覆盖方法
逻辑覆盖是一系列测试的通用术语。这种方法要求测试人员对程序的逻辑结构有清晰的理解。根据覆盖对象的不同和源程序句子的详细覆盖情况,常见的逻辑覆盖可分为六种类型:句子覆盖、决策覆盖、条件覆盖、决策-条件覆盖、条件组合覆盖和路径覆盖。
报表覆盖范围
语句覆盖是设计几个测试用例,然后运行被测程序,使每个可执行语句至少执行一次。这种覆盖使程序中的每个可执行语句都能被执行,但它是最弱的逻辑覆盖标准,效果有限,必须与其他方法交互使用。
决策覆盖范围
判断覆盖是指设计几个测试用例,然后运行被测试的程序,使程序中每个被判断的真分支和假分支至少经历一次。判断覆盖率略好于句子覆盖率,但不能保证能找出判断条件中的错误。因此,需要更强的逻辑覆盖标准来测试和判断内部条件。
条件覆盖:条件覆盖是设计几个测试用例,然后运行被测程序,使程序中判断的每个条件的可能值至少执行一次。路径覆盖:路径覆盖就是设计足够多的测试用例,执行程序所有可能的路径,这是一种覆盖率最高的覆盖技术。
z路径覆盖范围:路径覆盖由于路径太多而不便于使用,因此人们放弃了路径覆盖的一些次要因素并简化了循环机制,这大大减少了路径的数量,使覆盖这些有限的路径成为可能。这种覆盖方法称为Z路径覆盖。循环简化是指限制循环次数,只考虑循环执行一次和零次。用Z-路径覆盖法简化程序中的循环后,程序中只剩下两种结构:序列结构和分支结构。
路径测试方法:白盒测试有两种常用技术,一种是覆盖测试,另一种是路径测试。从流程图来看,程序的一次执行对应于从入口到出口的一条路径,对这条路径的测试就是路径测试。从广义上讲,任何与路径分析相关的测试都可以称为路径测试。路径测试基于程序控制流图,通过分析控制结构的循环复杂度,导出基本可执行路径集,进而设计测试用例。
程序路径表达式:在分析路径时,首先要解决的是确定每条路径和路径的数量。为了更直观形象地表达每条路径,我们可以使用弧序列或节点序列并引入两种运算:加法和乘法。弧A和弧B的相加表示为a+b,表示两条弧为“或”,为平行路径;弧A和弧B的乘积表示为ab,表示路径首先经过弧A,然后经过弧B,弧A和弧B依次相连。
基本路径测试:如果覆盖的路径数量被压缩到一定限度,它就变成了基本路径测试。基本路径测试是在程序控制流程图的基础上,通过分析控制结构的循环复杂性并导出基本可执行路径集来设计测试用例的方法。设计的测试用例应该确保程序的每个可执行路径在测试期间至少执行一次。基本路径测试方法包括以下五个方面:
1.根据详细设计或程序源代码,绘制程序的程序流程图;
2.根据程序流程图,绘制程序的控制流程图;
3.计算程序的循环复杂度。循环复杂度是一种软件度量标准,用于对程序逻辑的复杂度进行定量测试,该度量标准用于计算程序的基本独立路径的数量。
4.找到一条独立的道路。通过程序的程序流程图导出设置的基本路径,并列出程序的独立路径;
5.设计测试用例。根据程序结构和程序循环复杂性,设计用例的输入数据和预期结果,以确保基本路径集中每条路径的执行。
每个测试用例执行后,都会与预期结果进行比较。如果所有的测试用例都被执行了,你可以确定程序中所有的可执行语句都至少被执行了一次。但是一些独立路径通常不是完全隔离的,有时它们是程序正常控制流的一部分,因此对这些路径的测试可以是对另一条路径的测试的一部分。
循环试验
循环测试专门用于测试程序中的循环,可以进一步提高测试覆盖率。本质上,循环测试的目的是检查循环结构的有效性。通常,循环可分为简单循环、嵌套循环、链式循环和非结构化循环。
静态测试方法:静态测试方法主要是程序结构分析,可分为代码审查、代码遍历、控制流分析、数据流分析、信息流分析等。
代码审查
代码审查是由若干程序员和测试人员组成的审查小组通过阅读、讨论和争论对程序进行静态分析的过程。代码评审分为两步:第一步,组长提前将设计说明书、控制流程图、程序文本、相关需求和规范分发给组员,作为评审的依据。团队成员在充分阅读这些材料后进行审查的第二步是召开程序审查会议。在会议上,程序员首先解释程序的逻辑,程序员和其他团队成员可以提出问题,讨论并检查是否有错误。例如,在对一个局部小问题的修改方法的讨论中,可能会发现牵连其中的其他问题,甚至是设计模块的功能描述、模块之间的接口和系统整体结构中的重大问题,从而导致需求的重新定义、重新设计和重新验证,从而大大提高软件质量。
代码走查
代码演练与代码审查基本相同,其过程分为两步。第一步是先把材料发给检查组的每个成员,仔细研究后再开会。会议评审的过程不同于代码评审。参与者不是简单地阅读程序并对照错误清单进行检查,而是被允许充当计算机,也就是说,首先,测试团队的成员为被测试的程序准备许多有代表性的测试用例,并将其提交给走查团队。演练团队开会并集体充当计算机,这样测试用例就可以根据程序逻辑运行,并且可以随时记录程序的痕迹以供分析和讨论。
控制流分析
控制流分析是指检查程序的控制结构,以验证在编程过程中是否遵循了程序结构的某些规则,并在此基础上获得相关结构组件的语法树并揭示控制结构的缺陷。控制流关系图称为控制流图。图上的每个节点对应一个程序元素,两个节点之间有一条直接的弧线,这表明对应的两个元素在控制流关系中形成了一个序列对。控制流程图中的路径对应于潜在可执行程序元素的序列。执行路径意味着执行相应的程序元素序列。如果输入导致路径的执行,那么路径是可达的,否则是不可达的。通常,有许多具有周期的无线路径。即使没有循环,程序也可能有许多路径要分析。它有五种基本程序结构:线性结构、基本条件判断、多分支条件判断、while-do循环和do-while循环。控制流分析主要从三个方面分析程序结构:条件决策节点本身的复杂性;条件决策节点和循环节点对执行路径的影响;周期本身的复杂性。
数据流分析
数据流分析最早出现在生成有效目标代码的编译系统中,这种方法主要用于优化代码。数据流测试是一种基于程序控制流的结构化测试方法,从已建立的数据目标状态序列中发现异常。它的基本思想是变量的定义,通过重复引用和定义可以影响另一个变量的值或路径的选择。在测试数据流时,根据变量在被测程序中的定义和引用位置来选择测试路径。
信息流分析
信息流分析主要用于验证程序变量之间的信息传输是否遵循保密性要求,并通过分析输入数据、输出数据和语句之间的关系来检查程序错误。信息流分析主要用于分析是否存在无用语句。信息流分析可以列出对输入变量的所有可能的引用,检查程序的执行是否在任何指定点影响输出变量值的语句,并提供对输入-输出关系的检查,以查看每个输出值是否来自相应的输入值。
检测方法
程序仪表
程序插装使被测程序在保持原有逻辑完整性的基础上向程序中插入一些探针,并通过探针的执行抛出程序的运行特征数据。基于对这些特征数据的分析,可以得到程序的控制流和数据流信息,进而得到逻辑覆盖等动态信息。在程序中何处设置探针,如何设计探针以及如何对探针函数捕获的数据进行编码和解码。
程序插装在实践中应用广泛,可用于捕获程序执行过程中变量值的变化,也可用于检测程序的分支覆盖和语句覆盖。程序插装的关键技术包括检测什么信息、在程序中何处设置探针、如何设计探针以及探针函数捕获的数据的编码和解码。
领域测试
领域测试的“领域”是指程序的输入空间。领域测试方法基于对输入空间的分析,其理想结果是检查输入空间中的每个输入元素是否产生正确的结果。输入空间可以分成不同的子空间,每个子空间对应不同的计算。在调查了被测程序的结构后发现,子空间的划分是由程序中分支语句的谓词决定的,输入空间的一个元素以程序中某些特定语句的执行结束。领域测试基于对输入领域的分析,并选择适当的测试点进行测试。
符号测试
符号测试遵循传统的程序测试方法,通过运行被测程序来验证其可靠性。此外,由于符号测试的结果代表了一大类普通测试的运行结果,因此它实际上是为了证明程序是否接受这样的输入以及输出结果是否正确。从符号测试的使用情况来看,问题的关键是开发一个比传统编译器更强大的编译器。能够处理符号操作的编译器和解释器。
程序变异
程序变异测试是一种错误驱动的测试,针对的是特定的程序错误。由于人们无法找出程序中的所有错误,因此更现实的方法是尽可能缩小错误的范围,从而有助于测试某一类型的错误是否存在。这样可以很容易地关注对软件最有害的可能错误,实现更高的测试效率并降低测试成本。
覆盖标准
测试覆盖标准包括K.A.Foster的ESTCA覆盖标准和Woodward的分级LCSAJ覆盖标准。福斯特的经验覆盖率标准受到早期硬件测试方法的启发。通过大量实验,确定了程序中最容易出错的谓词部分,并得到了一组错误敏感测试用例分析(ESTCA)规则。Woodward等人提出了一种分层的LCSAJ覆盖准则。LCSAJ(线性码序列和跳转)的意思是线性码序列和跳转。LC SAJ是一组顺序执行的代码,以控制流跳转作为其终点。它表明覆盖率标准越高,就越难满足。
ESTCA覆盖标准:ESTCA coverage criterion也称为错误敏感测试用例分析规则,是基于程序中最容易出错的谓词部分的规则,属于大数据的范畴。ESTCA覆盖率准则针对的是程序员容易犯的错误,或者是围绕错误发生频繁的区域,从而提高发现错误的概率。它有三个规则。
规则1:对于A rel B(rel可以是)的分支谓词,应该适当选择A和B的值,以便当测试执行到分支语句时,A《B、A=B和A》B的情况分别出现一次。
规则2:对于类型为rel1 C的分支谓词(rel1可以》或
规则3:为外部输入变量赋值,使它们在每个测试用例中具有不同的值和符号,这些值和符号与同一组测试用例中其他变量的值和符号不一致。
LCSAJ覆盖标准:LCSAJ覆盖准则也称为线性码序列和跳转。LCSAJ是一组按顺序执行的代码,以控制流的跳转作为其终点。LCSAJ的起点是程序第一行的入口点或控制流可以到达的点。几个LCSAJ字符串首尾相连,最后一个LCSAJ端点就是程序的终点,构成了程序的一条路径。LCSAJ覆盖准则是一种分层覆盖准则;
第一层是语句;
第二层是分支覆盖;
第三层是一段LCSAJ覆盖,即程序的每个LCSAJ至少测试一次;
第四层是两个LCSAJ盖的任意连接,即程序中每两个首尾相连的LCSAJ将被测试一次;
第五层为任意连接的三层LCSAJ盖;
n+2层是每n个端到端LCSAJ组合测试一次,以此类推。
方法选择
白盒测试中测试方法的选择策略如下:
1.在测试中,首先分析了静态结构。
2.采用静态和动态相结合的方法。在静态结构分析、代码检查和静态质量度量之后,进行覆盖测试。
3.利用静态分析的结果,通过代码检查和动态测试进一步确认结果,使测试工作更加有效。
4.覆盖测试是白盒测试的重点,基本路径测试用于达到语句覆盖标准。对于关键模块,应该使用多个覆盖标准来衡量代码覆盖率。
5.不同的测试阶段有不同的侧重点。
应用领域
白盒测试适用于单元测试、集成测试和回归测试。单元测试是指检查和验证软件中最小的可测试单元。单元是一个软件组件,不能再细分为其他组件。软件工程师编写白盒测试用例来检查单元编码是否正确。
集成测试测试软件组件、硬件组件或两者来评估它们的交互。测试人员可以编写白盒测试用例以及黑盒测试用例来清楚地检查各个单元之间的接口。
回归测试,即系统或组件的选择性重新测试,以验证修改不会导致意外影响,并且系统或组件仍符合其指定要求。回归测试可以通过黑盒测试用例、白盒测试用例或两者的结合来完成。白盒测试用例以及集成测试用例可以被保存并允许作为回归测试的一部分。