白盒测试用例设计

白盒测试又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试是一种测试用例的设计方法,盒子对应的是被测试的测试,”白盒”法全面了解程序内部逻辑结构、对所有逻辑路径进行测试。”白盒”法是穷举路径测试。测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。

静态白盒测试

静态测试:不实际运行被测系统本身,检查文档内容、界面、代码规范等

静态白盒测试:不实际运行被测系统本身,检查和审查代码的设计、结构,也称为结构化分析。尽早发现程序中的缺陷,可以发现30%-70%的缺陷,可以为黑盒测试人员提供测试思路

代码检查应在编译和动态测试之前进行,在检查前,应准备好需求描述文档、程序设计文档、程序的源代码请当、代码编译标准和代码缺陷检查表等。在实际使用中,代码检查能快速找到缺陷,发现30%~70%的逻辑设计和编码缺陷,而且代码检查看到的问题本身而非征兆。

1)桌面检查

这是一种传统的检查方法,由程序员检查自己编写的程序。程序员在程序通过编译之后,对源程序代码进行分析、检验,并补充相关文档,目的是发现程序中的错误。由于程序员熟悉自己的程序及其程序设计风格,桌面检查由程序员自己进行可以节省很多的检查时间,但应避免主观片面性

2)代码审查

由若干程序员和测试员组成一个审查小组,通过阅读、讨论和争议,对程序进行静态分析的过程。

代码审查分两步:第一步,小组负责人提前把设计规格说明书、控制流程图、程序文本及有关要求、规范等分发给小组成员,作为审查的依据。小组成员在充分阅读这些材料后,进入审查的第二步,召开程序审查会。在会上,首先由程序员逐句简介程序的逻辑。在此过程中,程序员或其他小组成员可以提出问题,展开讨论,审查错误是否存在。实践表明,程序员在讲解过程中能发现许多原来自己没有发现的错误,而讨论和争议则促进了问题的暴露。

在会前,应当给审查小组每个成员准备一份常见错误的清单,把以往所有可能发生的常见错误罗列出来,供与会者对照检查,以提高审查的失效。这个常见的错误清单也成为检查表,它把程序中可能发生的各种错误进行分类,对每一类错误列出尽可能多的典型错误,然后把它们制成表格,供再审查时使用

3)代码走查

与代码审查基本相同,分为两步,第一步也是把材料分给走查小组的每个成员,让他们认真研究程序,然后再开会。开会的程序与代码审查不同,不是简单地读程序和对照错误检查表进行检查,而是让与会者“充当”计算机,即首先由测试组成员为所测试程序准备一批有代表性的测试用例,提交给走查小组。走查小组开会,集体扮演计算机角色,让测试用例沿程序的逻辑运行一遍,随时记录程序的踪迹,供分析和讨论用。

人们借助测试用例的媒介作用,对程序的逻辑和功能提出各种疑问,结合问题开展热烈的讨论和争议,能够发现更多的问题。

4)代码扫描工具

代码检查非常耗费时间,而且代码检查需要知识和经验的积累。代码检查可以使用测试软件进行自动化测试,以利于提高测试效率,降低劳动强度

现在白盒测试中源代码扫描越来越成为一种流行的技术,使用源代码扫描产品对软件进行代码扫描,一方面可以找出潜在的风险,从内对软件进行检测,提高代码的安全性,另一方面也可以进一步提高代码的质量。

比较主流的工具有:Fortify公司的Fortify SCA,Security Innovation公司的Checkmarx Suite和Armorize公司的CodeSecure。

动态白盒测试

主要关注的是动态设计方法。动态分析的主要特点是当软件系统在模拟的或真实的环境中执行之前、之中和之后,对软件系统行为的分析。动态分析包含了程序在受控的环境下使用特定的期望结果进行正式的运行。它显示了一个系统在检查状态下是正确还是不正确。

设计测试用例,根据测试用例执行被测程序(代码),验证代码的逻辑结构是否满足需求

逻辑覆盖法

逻辑覆盖法是通过对程序逻辑结构的遍历实现程序的覆盖。

根据覆盖目标的不同和覆盖源程序语句的详尽程度,逻辑覆盖又可分为:

1. 语句覆盖(SC)

语句覆盖是最基本的结构覆盖要求,在六种逻辑覆盖标准中是最弱的。语句覆盖要求设计足够多的测试用例,使得程序中每条语句至少被执行一次,尽可能达到100%的覆盖率

优点:可以很直观地从源代码得到测试用例,无须细分每条判定表达式。

缺点:由于这种测试方法仅仅针对程序逻辑中显式存在的语句,但对于隐藏的条件和可能到达的隐式逻辑分支,是无法测试的。例如将上例中判断条件改成if(x>0||y>0) 也是可以通过测试的,所以单纯的语句覆盖不能准确的判断运算中的逻辑关系错误。

2. 判定覆盖(DC)

又称分支覆盖,设计若干个测试用例,运行所测程序,使程序中每个判断的取真分支和取假分支至少执行一次。即:程序中的每个分支至少执行一次。每个判断的取真、取假至少执行一次。

只要满足判定覆盖标准就一定满足语句覆盖标准。

同样将上例中判断条件改成if(x>0||y>0) ,还是通过测试。所以判定覆盖会忽略条件中的or情况

优点:判定覆盖比语句覆盖要多几乎一倍的测试路径,当然也就具有比语句覆盖更强的测试能力。同样判定覆盖也具有和语句覆盖一样的简单性,无须细分每个判定就可以得到测试用例。

缺点:往往大部分的判定语句是由多个逻辑条件组合而成(如:判定语句中包含AND、 OR、CASE)。若仅仅判断其整个最终结果,而忽略每个条件的取值情况,必然会遗漏部分测试路径。

3. 条件覆盖(CC)

条件覆盖设计足够多的测试用例,使得判定中的每个条件获得各种可能的结果,即每个条件至少有一次为真值,有一次为假值。

由上图可知,虽然满足了条件100%覆盖,但是P1并没有覆盖到为T的情况

优点:显然条件覆盖比判定覆盖,增加了对符合判定情况的测试,增加了测试路径。

缺点:要达到条件覆盖,需要足够多的测试用例,但条件覆盖并不能保证判定覆盖。条件覆盖只能保证每个条件至少有一次为真,而不考虑所有的判定结果。

4. 判定条件覆盖(CC)

设计足够多的测试用例,使得判定中每个条件的所有可能结果至少出现一次,每个判定本身所有可能结果也至少出现一次。

满足判定条件覆盖一定能够满足条件覆盖,判定覆盖和语句覆盖。

同样将上例中判断条件改成if(x>0||y>0) ,还是通过测试。所以判定条件覆盖还是会忽略条件中的or情况

优点:判定/条件覆盖满足判定覆盖准则和条件覆盖准则,弥补了二者的不足。

缺点:判定/条件覆盖准则的缺点是未考虑条件的组合情况。

5. 条件组合覆盖(MCC)

要求设计足够多的测试用例,使得每个判定中条件结果的所有可能组合至少出现一次。— 判定之间无需组合,所以条件组合的总数是各判定中条件组合数相加,而不是相乘。

满足条件组合条件覆盖一定能够满足条件覆盖,判定覆盖,判定条件覆盖和语句覆盖。

上图的问题是没有覆盖到路径:a-b-d-f

优点:多重条件覆盖准则满足判定覆盖、条件覆盖和判定/条件覆盖准则。

缺点:线性地增加了测试用例的数量。无能保证所有路径被执行

6. 路径覆盖

设计足够的测试用例,覆盖程序中所有可能的路径。

但是从上图可见,并未满足判定条件100%覆盖,自然也不能满足100%条件覆盖。

优点:这种测试方法可以对程序进行彻底的测试,比前面五种的覆盖面都广。

缺点:由于路径覆盖需要对所有可能的路径进行测试(包括循环,条件组合,分支选择等).那么需要设计大量、复杂的测试用例,使得工作量呈指数级增长。

基本路径测试法

在实际工作中,程序往往会包含大量的循环,分支等,那么用路径覆盖是很难全部覆盖的。

基本路径测试法是在程序控制流图的基础上,通过分析控制构造的环路复杂性,导出基本可执行路径集合,从而设计测试用例的方法。设计出的测试用例要保证在测试中程序的语句覆盖100%,条件覆盖100%。

第一步:画出控制流图

  流程图用来描述程序控制结构。可将流程图映射到一个相应的流图(假设流程图的菱形决定框中不包含复合条件)。在流图中,每一个圆,称为流图的结点,代表一个或多个语句。一个处理方框序列和一个菱形决测框可被映射为一个结点,流图中的箭头,称为边或连接,代表控制流,类似于流程图中的箭头。一条边必须终止于一个结点,即使该结点并不代表任何语句(例如:if-else-then结构)。由边和结点限定的范围称为区域。计算区域时应包括图外部的范围。

流图只有二种图形符号:

  图中的每一个圆称为流图的结点,代表一条或多条语句。

  流图中的箭头称为边或连接,代表控制流

在将程序流程图简化成控制流图时,应注意:

  1)在选择或多分支结构中,分支的汇聚处应有一个汇聚结点。

  2)边和结点圈定的范围叫做区域,当对区域计数时,图形外的区域也应记为一个区域。

​ 3)如果判断中的条件表达式是由一个或多个逻辑运算符 (OR, AND, NAND, NOR)连接的复合条件表达式,则需要改为一系列只有单条件的嵌套的判断

第二步:计算圈复杂度

  圈复杂度是一种为程序逻辑复杂性提供定量测度的软件度量,将该度量用于计算程序的基本的独立路径数目,为确保所有语句至少执行一次的测试数量的上界。独立路径必须包含一条在定义之前不曾用到的边。

第三步:导出可执行路径

  一条独立路径是指,和其他的独立路径相比,至少引入一个新处理语句或一个新判断的程序通路。V(G)值正好等于该程序的独立路径的条数。

第四步:设计测试用例

  为了确保基本路径集中的每一条路径的执行,根据判断结点给出的条件,选择适当的数据以保证某一条路径可以被测试到

总结

白盒测试主要应用与单元测试阶段,一般先静态后动态。设计用例一般使用基本路径测试,重点模块使用多种覆盖率标准

优点

a.迫使测试人员去仔细思考软件的实现

b.可以检测代码中的每条分支和路径

c.揭示隐藏在代码中的错误

d.对代码的测试比较彻底

e.最优化

缺点

a.代价昂贵

b.无法检测代码中遗漏的路径和数据敏感性错误

c.不验证规格的正确性