【从零开始学习计算机科学】软件测试(五)白盒测试

白盒测试

概述

白盒测试也称结构测试或逻辑驱动测试,通过了解软件系统的内部工作过程,设计测试用例来检测程序内部动作是否按照规格说明书规定的正常进行,按照程序内部的结构测试程序,检验程序中的每条通路是否都有能按预定要求正确工作。
白盒测试基于一个应用代码的内部逻辑知识,即基于覆盖全部代码、分支、路径、条件,使用程序设计的控制结构导出测试用例。

测试原则

  • 保证一个模块中所有路径至少被测试一次;
  • 所有逻辑值都要测试真和假两种情况;
  • 检查程序的内部数据结构是否有效;
  • 检查上、下边界及可操作范围内运行所有循环。

白盒测试的依据

  • 软件需求报告;
  • 软件需求规格说明;
  • 程序设计文档;
  • 软件界面设计;
  • 编码规范;
  • 开发命名标准等等。

白盒测试的类别

按测试对象白盒测试可分为:

  • 软件公用问题的测试;
  • 语言测试;
  • 业务对象测试;
  • 数据类型测试;
  • 界面测试;
  • 数值对象测试;
  • 数据管理对象测试。

静态测试

静态测试通常不涉及代码的运行。

静态测试-代码检查

代码检查是软件静态测试中常用的软件测试方法之一,更容易发现架构以及时序相关等较难发现的问题;帮助团队成员统一编程风格,提高编程技能等。
代码检查被公认为是一个提高代码质量的有效手段。
代码审查包含对错误代码的检查,和不好的编码风格代码的检查。
一份良好的代码,应具有以下特性:

  • 可靠性:事实证明按照某种标准或规范编写的代码比不这样做的代码更可靠,软件缺陷更少。
  • 可读性维护性:符合标准和规范的代码易于阅读、理解和维护。
  • 可移植性:如果代码符合标准,迁移到另一个平台就会轻而易举,甚至完全没有障碍。

代码检查的内容主要有可追溯性、逻辑、数据、接口、文档、注释、异常处理、内存、其他。

代码检查过程:
  1. 代码检查策划:包括项目负责人分配代码审查任务;确定代码审查策略:依据软件开发文档,确定软件关键模块,作为代码审查重点;将复杂度高的模块也作为代码审查的重点;确定代码审查单;确定代码审查进度安排。

  2. 代码检查实施,其包括代码讲解:软件开发人员详细向测试人员讲解代码实现情况,测试人员提出问题和建议;静态分析。采用静态分析工具进行分析,有利于软件测试人员在后续代码审查时对软件建立宏观上认识;规则检查:采用静态分析工具对源程序进行编码规则检查,对于工具报出的问题再由人工进行进一步的分析以确认软件问题。

  3. 正式代码检查

    • 独立审查:测试人员根据项目负责人的工作分配,独自对自己负责的软件模块进行代码审查。
    • 会议审查:项目负责人主持召开会议,测试人员和开发人员参加;测试人员就独立审查发现的问题和疑问与开发人员沟通,并讨论形成一致意见。
    • 更改确认:开发人员对问题进行处理,代码审查人员对软件的处理情况进行确认,验证更改的正确性。
  4. 代码检查总结:代码审查工作结束后,项目负责人总结代码审查结果;编写测试报告,对软件代码质量进行评估,给出合理建议。详细记录代码审查提出的所有问题及最终结论可以供其他软件项目代码审查借鉴。

静态测试-代码走查

代码走查是软件静态测试方法之一,是通过对代码的阅读,检查发现程序代码中的问题。
具体方法由测试人员组成小组,准备一批有代表性的测试用例,集体扮演计算机的角色,沿程序的逻辑,逐步运行测试用例,查找被测软件缺陷。
经验表明,代码走查通常能够有效地查找出大部分的逻辑设计和编码错误。一旦发现错误,通常就能在代码中对其进行精确定位,降低了调试的成本。代码走查过程通常可以发现成批的错误,这样错误就可以一同得到修正。

走查小组的组成:通常由三至五人组成,其中一个人扮演类似代码检查过程中协调人的角色,一个人担任秘书的角色,还有一个人担任测试人员。关于小组的组成结构,一般建议包括:一位极富经验的程序员;一位程序设计语言专家;一位程序员新手(可以给出新颖、不带偏见的观点);最终维护程序的人员;一位来自其他不同项目的人员;一位来自该软件编程小组的程序员。

代码走查过程:
  1. 准备阶段:在走查会议前几天分发有关材料,走查小组详细阅读材料,认证研究程序。

  2. 生成实例:小组中被指定为测试人员的那个人应提前准备好一些书面的有代表性的测试用例。

  3. 执行走查:在走查会议期间,每个测试用例都在人们脑中进行推演。也就是说,把测试数据沿程序的逻辑结构走一遍。程序的状态(如变量的值)记录在纸张或白板上以供监视。

  4. 形成报告:会后将发现的错误形成报告,并交给程序开发人员。对发现错误较多或发现重大错误,在改正错误后再次进行会议走查。

走查与检查的比较

走查的准备阶段是通读设计和编码;应准备好需求描述文档、程序设计文档、程序的源代码。而检查的准备阶段的材料是清单、代码编码标准和代码缺陷检查表。走查的形式是非正式会议,检查的形式是正式会议。走查的参加人员以开发人员为主,检查的参加人员是项目组成员包括测试人员。检查需要的技术是缺陷检查表。走查和检查通常都是限时、不要现场修改代码。走查生成的文档是会议记录,检查生成的文档是静态分析错误报告。走查和检查的目标都是使得代码标准规范,无逻辑错误。

静态测试-静态结构分析

静态结构分析以图形的方式表现程序的内部结构,例如函数调用关系图、函数内部控制流图。
静态结构主要分析:可以检查函数的调用关系是否正确;是否存在孤立的函数而没有被调用;明确函数被调用的频繁度,对调用频繁的函数可以重点检查;编码的规范性;资源是否释放。

动态测试

动态测试通过运行软件来检验软件的动态行为和运行结果的正确性。

动态测试流程

首先,选取定义域有效值,或定义域外无效值;
然后,对已选取值决定预期的结果;用选取值执行程序;执行结果与对已选取值决定预期的结果相比,不吻合程序有错;保证每个模块的所有独立路径至少被使用一次;对所有的逻辑值均测试,即包括true和false上下边界及可操作范围内运行所有循环;检查内部数据结构以确保其有效性。

动态测试主要分为以下几种:

  • 结构性测试。通常采用语句测试、分支测试或路径测试。
  • 正确性测试。基于产品功能规格说明书、从用户角度针对产品特定的功能和特性所进行的验证活动,以确认每个功能是否得到完整的实现,用户能否正常使用这些功能。

白盒测试常用技术主要有:逻辑覆盖法、插桩技术、基本路径测试法、域测试法、符号测试、路径覆盖法、程序变异测试法。

逻辑覆盖法

逻辑覆盖是以程序内部的逻辑结构为基础的设计测试用例的技术。它属于白盒测试。根据覆盖目标的不同和覆盖源程序语句的详尽程度,逻辑覆盖又可分为:

  1. 语句覆盖:语句覆盖就是设计若干个测试用例使得程序中每一个可执行语句至少执行一次。使用测试用例越少越好。语句覆盖在测试中主要发现缺陷或错误语句。(判定语句不会考虑)

  2. 判定覆盖:判定覆盖就是设计若干测试用例使得每个判定的取真分支和取假分支至少执行一次。判定覆盖只考虑整个表达式的取值,并不考虑到表达式内部变量的取值。

  3. 条件覆盖:只考虑到每个判定语句中的每个表达式,没有考虑到各个条件分支即不能够满足判定覆盖。

  4. 条件/判定覆盖:判定条件覆使判定中的每个条件的所有可能(真/假)至少出现一次,并且每个判定本身的判定结果也至少出现一次。

  5. 条件组合覆盖:条件组合覆盖使得每个判定中条件的各种可能组合都至少出现一次(以数轴形式划分区域,提取交集,建立最少的测试用例)。满足条件组合覆盖一定满足判定覆盖、条件覆盖、判定条件覆盖。

  6. 修正判定条件覆盖:每一个程序模块的入口和出口点都要考虑至少要被调用一次,每个程序的判定到所有可能的结果值要至少转换一次;程序的判定被分解为通过逻辑操作符(and,or)连接的bool条件,每个条件对于判定的结果值是独立的。

  7. 路径覆盖:路径覆盖使得每个路径至少被执行一次。

越往下覆盖率相对越高。

在这里插入图片描述

各个覆盖之间的关系

判定覆盖包含语句覆盖;条件覆盖包含语句覆盖;判定/条件覆盖同时满足判定和条件覆盖;条件组合覆盖满足条件组合覆盖,则一定满足判定/条件覆盖。

逻辑覆盖法就是根据逻辑覆盖的某个等级设计出满足其条件的一组测试用例。

插桩技术

程序插桩是一种基本的动态测试方法,向源程序中添加一些语句实现对程序代码的执行、变量的变化等情况的检查,可以获得程序的控制流和数据流信息。
如果我们想要了解一个程序在某次运行中可执行语句被覆盖的情况,或是每个语句的实际执行次数,最好的办法就是利用插装技术,它在软件测试技术上占有非常高的地位。最简单的插装:在程序中插入打印语句printf(“ …”)语句。

插桩位置通常是:程序的第一条语句;分支语句的开始;循环语句的开始;下一个入口语句之前的语句;程序的结束语句;分支语句的结束;循环语句的结束。

插桩策略:

  1. 语句覆盖探针(基本块探针):在基本块的入口和出口处,分别植入相应的探针,以确定程序执行时该基本块是否被覆盖。
  2. 分支覆盖探针:c/c++语言中,分支由分支点确定。对于每个分支,在其开始处植入一个相应的探针,以确定程序执行时该分支是否被覆盖。
  3. 条件覆盖探针:c/c++语言中,if, swich,while, do-while, for 几种语法结构都支持条件判定,在每个条件表达式的布尔表达式处植入探针,进行变量跟踪取值,以确定其被覆盖情况。

设计插桩程序需要注意的几点:

  • 探测那些信息;
  • 在什么位置设置探针;
  • 设置多少个探测点;
  • 特定位置插入用以判断变量特性的语句。
  1. 断言测试:断言测试用于检查在程序运行过程出现的一些本“不应该”发生的情况。也就是在一个应该正确的地方,加一条判断来验证程序运行时,它是否真正如当初预料的那样,具有预期的正确性。
    断言测试就是在程序中插入断言,插入断言的根本目的是用于帮助程序的调试与排错,因此本质上它是属于测试代码,是一种特殊的插桩语句,而不是属于真正的应用程序模块的一部分。

基本路径法

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

基本路径法在程序控制流图的基础上,通过分析控制构造的