软件测试(二)-静态测试-数据流分析
1. 数据流分析的相关概念
基于结构测试的方案还有一种测试方法,就是数据流分析测试。 数据流分析测试是指变量 定义(赋值)与使用位置的 一种基于程序结构性的测试方法。该分析方法重点关注变量的定义与使用。在选定的一组代码中搜索某个变量所有的定义、使用位置,并检查在程序运行时该变量的值将会如何变化,从而分析是否是 Bug 的产生原因。
数据流分析与路径测试的区别在于:路径测试基本上是从数学(控制流图)角度来分析的,而数据流测试则是利用了变量之间的关系,通过定义-使用路径和程序片,得到一系列的测试指标用于衡量测试的覆盖率。
数据流分析定义
数据流指的是数据对象的顺序和可能状态的抽象表示。 数据对象的状态可以是创建/定义(Creation/Defined)、使用(Use)和清除/销毁(Killed/Destruction)。数据值的变量存在从创建、使用到销毁的一个完整状态。 编码错误导致的变量赋值错误检查是发现代码缺陷或错误的一种有效方法。实际上该方法可认为是路径测试的“真实性”检查,是对基于路径测试的一种改良。
数据流分析的功能作用
数据流分析的作用是用来测试变量设置点和使用点之间的路径。这些路径也 称为“定义-使用对”(definition-use 或 du-pairs)或“设置-使用对”。通过数据流分析而生成的测试集可用来获得针对每个变量的“定义-使用对”的 100%覆盖。但是,要追踪整个程序代码中的每个变量的设置和使用时,并不需在测试时考虑被测对象的控制流。
程序代码路径中首次出现的变量可能存在的状态组合
~d 变量不存在或没定义(通过 ~ 表示),然后定义(d),~d 是正确的。
~u 变量不存在或没定义,然后使用(u), ~u 是错误的,因为变量使用之前必须定义。
~k 变量不存在或没定义,然后撤销(k), ~k 可能是错误的,因在创建变量之前撤销变量可能是一个潜在的编程错误。
d、u、k 的具体含义:
d: 变量声明或定义,且变量已赋值
u: 读取及使用
k: 声明或定义变量,但还未为其赋值或已释放变量(模块或函数 结束时),针对程序代码路径中的变量执行的顺序,变量状态 d、u、k 的组合可能会有 33=9 种情况
dd:变量赋值后再次赋值,可疑的或可能是编程错误。
du:变量赋值后使用,正确。是程序代码中的正常情况。
dk:变量定义后撤销,可疑的或可能是编程错误。
ud:变量使用后再定义,可以接受。
uu:变量使用之后再使用,可以接受。
uk:变量使用之后撤销,可以接受。
kd:变量撤销后再定义,可以接受,变量撤销之后重新定义。
ku:变量未定义或撤销后使用,严重问题,在变量不存在或没有定
义的情况下,使用变量是错误的。
kk:变量未定义或撤销之后再撤销,可能是编程错误。
数据流分析可基于数据流图而展开
数据流图类似于控制流图,描述了测试对象代码的处理过程。同时也详细描 述了代码中变量的创建、使用和撤销的状态。通过检查数据流图来验证测试对象代码中每个变量的状态组合是否正确。
图 1 是一个数据流图的例。
通过分析每个变量的执行顺序状态,可以发现存在的一些问题。 这里,分析例中三个变量 x,y,z,其存在的状态组合如下:
变量 x,其状态的可能组合:
Define x
Use y
Kill z
Define y
Use z
Define x
Use x
Use z
Kill z
Use x
Define z
Use y
Use z
Kill y
Define z
~d:正确的情况
dd:定义之后再定义,可能是编程错误
du:定义之后使用,正确情况
变量 y,其状态的可能组合:
~u: 定义变量之前使用变量,严重错误
ud: 变量使用后再定义,可接受
du: 变量定义之后使用,正确情况
uk:变量使用之后撤销,可接受
dk:变量定义之后撤销,可能是编程错误
变量 z,其状态的可能组合:
~k:定义变量之前撤销变量,可能是编程错误
ku:变量撤销后使用变量,严重错误
uu: 使用变量后再使用变量,正确情况
ud:变量使用之后再定义,可接受
kk:撤销变量后再撤销,可能是编程错误
kd:变量撤销后再定义,可接受
du:变量定义之后使用变量,正常情况
因此,针对本例的数据流分析中可得出存在着下列问题:(对照前面
的组合状态定义和三个变量的组合状态)
变量 x 存在 dd 的编程错误
变量 y 存在 ~u 和 dk 的编程错误
变量 z 存在 ~k、ku、kk 编程错误
数据流分析方法是基于形式化的 从上可看出,数据流分析测试方法实 际上是形式化的。这样的方式,便于用来构造算法从而能够实现自动化的分析。
这里作如下定义:
- P 代表程序,G(P)为程序数据流图,V 为变量集合,P 的所有路径集合为 PATH(P)。
- 节点 n 是变量 v 的定义节点,记 DEF(v, n)。 输入、赋值、循环语句与 过程调用都是节点定义的实例。如果执行了定义这种语句的节点,那么与该变量关联的存储单元的内容就会改变。
- 节点 n 是变量 v 的使用节点,记 USE(v, n)。 输入、赋值、条件、循环控制语句、过程调用,都是使用节点语句实例。如果执行对应这种语句的节点,那么与该变量关联的存储单元的内容就保持不变。
- 例如 USE(v, n) 是谓词使用 (条件判断语句中),记为 P-use。
- 例如 USE(v, n) 是计算使用 (计算表达式中),记为 C-use。
- 变量 v 的定义-使用路径(define-use path), 记为 du-path。如果 PATH 中的某个路径,定义节点 DEF(v, n) 为该路径的起始节点,使用节点 USE(v, n)为该路径的终止节点,则该路径是 v 的定义-使用路径。
- 变量 v 的定义-清除路径(define-clear path),记为 dc-path。 如果变 量 v 的某个定义-使用路径,除了起始节点之外没有其他定义的节点,则该路径是变量 v 的定义-清除路径。
- 程序片:S (v,n) 指节点 n 之前的所有对 v 中的变量值,做出过‘操作’的所有语句片段的全部。显然,做出操作的一定是上面所述的 USE(v,n),这里的使用路径包括直接和间接的。
举例说明,比如说在结点 n 有个变量 a=a+b+c, 那么很显然,这里影响 a 的值包括 a,b,c, 所以自然要将在结点 n 前影响到值
a,b,c 三个变量的所有结点都要考虑。若出现了一个常量语句,如 b=1230, 即说明对 b 已经没有影响了。 程序片的一个最大使用是用来排除程序片段是否存在问题的。比如现在有两个程序片 p1、p2。一个是第 8 行的 v, 一个是第 10 行的 v,假设第 8 行和第 10行之间没有任何常量对 v 进行赋值,那么 p2= ( p1,9,10), 这里假设第 9 行和第10 行影响了 v 值,那么如果 8 行之前的程序片 p1 中的变量 v 没有发生问题,而第 10 行的程序片 p2 出现了问题,那么变量 v 的异常必定在 p2- p1 这段程
序片上。因此程序片能够很快定位出异常在哪里。 数据流测试常应用于计算密集程序。数据流能方便的描述程序的部分片段的结构,定义使用路径具有和程序片相似的性质,如果 p1 是包含了 p2 的一条定义使用路径,如果 p2 没有出现问题,那么问题必然出现在 p1-p2 这段路径上了。然后片与定义使用路径一个区别在于片并不能很好的反应测试用例,这个也很容易理解,因为片是反应局部状况的,而定义使用路径则是基于路径的,路径是具有结构化性质指标的。这些就是基于数据流测试的全部。
2.数据流覆盖指标(拉普斯-韦约克)
拉普斯-韦约克(Rapps-Weyuker)数据流覆盖层次结构图如图 2 所示。
这个数据流覆盖指标层次结构图描述了数据的“定义-使用”对,找出所有变量的定义-使用路径情况。实际上,这是变量的定义-使用路径情况的检查结构。当每个层次结构都检查完成,则表明针对变量的定义-使用路径达到 100% 的覆盖。 定义-使用路径是一组定义所得到的测试指标,包括全路径、全定义-使用路径、全使用、全计算使用/部分谓词使用、全谓词使用/部分计算使用、全定义、全谓词使用、全边、全节点。
图 2 Rapps-Weyuker 数据流覆盖层次结构图
数据流测试方法是在程序代码经过的路径上检查变量的数据的用法。这主要是为了发现“定义-使用”异常的缺陷。这里异常是指可能会导致程序失效的情形。如发现了数据流异常:“没有初始化就读取了变量的值,或根本没有使用变量的值“。异常可能会触发程序运行的风险,但并非数据流异常都会导致错误的程序行为发生(即失效)。因此对发现的数据流问题,需深入检查确定是否存在定义-使用问题。
2. 数据流分析的测试举例
【例 1】数据流分析举例
某片段程序如下:
1 a=5; //定义 a 并赋值 5
2 while (c1) {
3 if (c2) {
4 b=a*a; //使用 a
5 a=a-1; //定义且使用 a
6 }
7 print(a); //使用 a
8 print(b); } //使用 b
分析过程: 数据流覆盖指标(拉普斯-韦约克)层次结构图来描述上述程序的数据“定义-使用”对,并找出所有变量的“定义-使用“路径,可得到该程序数据流图 G(P) (图 3 所示)的使用路径 du-path 与清除路径 dc-path,定义-使用节点(表 1 所示)和定义-使用路径(表 2 所示),得到路径图 DD(图 4所示)
图 3 程序数据流图 G(P) 图 4 路径图 DD
du-path(使用路径) dc-path(清除路径)
1234 yes
12345 yes
1234567 no
567 yes
表 1 定义/使用节点
变量 | 定义节点 | 使用节点 |
a | 1,5 | 4,5,7 |
b | 4 | 8 |
表 2 定义/使用路径
变量 | 路径(开始、结束)节点 | 是定义清除吗? |
a |
1,4 1,5 1,7 5,7 |
是 否 否 是 |
b | 4,8 | 是 |
【例 2】进行给出的下列程序的数据流分析
1 long Add(int a, int b, int c )
2 { a=x+a; 3 while(a<1000 ) {
4 if( b<10||a>5 )
{
5 x=y+b; } else {
6 y=y+a; }
7 y=x+y; }
8 return c ;
}
分析: 分析过程与【例 1】基本一致,这里不再赘述。这里主要分析该程序的变量的定义-使用情况:
- -引用未定义的变量;
- -所使用变量未被定义;
- -找出循环内定义的变量;
- -变量的赋值。
结果:
(1) 数据流图 如下图
(2)变量的定义-使用 如下表
节点 | 被定义变量 | 被使用变量 |
1 | a、b、c | |
2 | a | x、a |
3 | a | |
4 | a、b | |
5 | x | y、b |
6 | y | y、a |
7 | y | X、y |
8 | c |
主要参考文献
1.《软件测试教程(第 3 版)》,贺平,电子工业出版社,2014
2.《软件测试设计》,马均飞 郑文强,电子工业出版社,2011
软件测试(二)-静态测试-数据流分析相关推荐
- 阿里软件测试二面通过率,阿里测开一面二面三面hr面
阿里本地生活饿了么测开岗位 一面: 1.自我介绍 2.项目中怎么做测试的 3.你了解测试是什么 4.什么是单测 5.冒泡排序 感觉一面简单的出奇.... 二面: 面试官是个可爱的小姐姐- 1.自我介绍 ...
- 软件测试(二)——软件测试基础篇
软件测试的生命周期 软件测试的生命周期:需求分析→测试计划→ 测试设计.测试开发→ 测试执行→ 测试评估 软件测试&软件开发生命周期 需求阶段--测试人员了解需求.对需求进行分解, 得出测试需 ...
- 软件测试桌面检查,静态测试的主要方法 - 测试天下,梦寻人生 - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
静态测试主要指针对文档,而不是程序代码,进行测试. 静态测试的主要方法有: 桌面检查(Desk checking) 桌面检查是最不正式,也是最省时的静态测试技术.在所有的技术中,桌面检查是唯一一个被鼓 ...
- 软件测试 中静态测试与动态测试的区别
1.测试部分的不同 静态测试是指测试不运行的部分:只是检查和审阅,如规范测试.软件模型测试.文档测试等.动态测试是通常意义上的测试,也就是运行和使用软件. 2.测试方式不同 静态测试,通过评审文档.阅 ...
- 阿里软件测试二面:adb 连接 Android 手机的两种方式,看完你就懂了
前言 随着现在移动端技术的突飞猛进,导致现在市场上,APP 应用数不胜数,那对于测试工程师而言,对于 APP 的测试,那基本就是一个必修课了. 今天,我就来给大家介绍一下,adb 连接 Android ...
- 静态程序分析chapter3 - 数据流分析详述(Reaching Definitions、Live Variables、Available Expressions Analysis)
文章目录 二. 数据流分析 introduction1 introduction2 输入和输出状态 转换函数 数据流分析应用 1,Reaching Definitions Analysis 概述 用途 ...
- 软件测试常见笔试面试题(一)
一.什么是软件测试 二.软件测试的目的 三.什么是需求文档测试 四.什么是设计文档测试 五.α测试是什么 六.β测试是什么 七.什么是驱动模块 八.什么是桩模块 九.什么是白盒测试,有几种方法 十.软 ...
- 【软件测试】什么软件测试,软件测试和研发的区别
目录 一.软件测试 二.软件测试与研发的区别 1,软件测试与调试的区别 2,难易程度 三.第一个测试 一.软件测试 验证软件是否满足用户的需求(不是以软件测试人员的主观意愿去判断软件质量的,它是有标准 ...
- 01.软件测试基础知识整合
软件测试基础 前言 一.什么是软件测试 二.软件测试的目的 三.软件测试的基本流程 四.测试分类 五.测试用例 1.什么是测试用例 2.测试用例的重要性 3.测试用例的设计方法 4.测试点分析 5.如 ...
- 学习笔记之 软件测试基础理论知识
目录 一.什么是软件测试 二.测试对象 三.测试原则 四.测试流程(功能) 1. 了解产品功能需求 2. 制定测试计划 3. 编写测试用例 3.1 需求文档分析 3.2 功能模块划分 3.3 编写测试 ...
最新文章
- 机器学习——XGBoost大杀器,XGBoost模型原理,XGBoost参数含义
- YARN集群维护部分问题汇总
- scrum工具四款可参考
- Python多分类问题下,micro-PR计算以及macro-PR计算
- SwiftUI 发展现状和学习指南
- ubuntu下Tensorflow 报错: ImportError: No module named 'matplotlib'
- android常见面试问题
- 【渝粤题库】陕西师范大学700004 植物生理学
- maven项目中整合grunt构建工具(二)-js合并、压缩技术
- Series.str.split([pat, n, expand])
- 微信帐号被封零钱怎么办?微信针对封停帐号的零钱提取出了一个流程
- 物联网标准NB-IoT和LoRa,究竟谁能更胜一筹?
- 赴日软件工程师,据说很火
- 泰晤士高等教育世界大学排名(400强)—前50位
- (数据结构)栈(LIFO结构)——概念、进栈、出栈、先进后出的特性
- C++——队列应用——显示二项式系数
- 30万人追更,年度重磅Go图书出版,百万流量博主带你学习Go底层原理
- 绘制热力图seaborn.heatmap,cmap设置颜色的参数
- 马里奥(附代码windows)
- 计算机图形学笔记十:Geometry3(网格处理)
热门文章
- Elasticsearch - 短语匹配(match_phrase)以及slop参数
- 李嘉诚再次助攻华为 用事实打脸“别让李嘉诚跑了”
- C++ 常用数学函数
- 魔兽对战平台服务器更新维护什么,官方对战平台每天5点维护是个什么梗
- 【转】浅谈半导体工艺变革
- 科技企业的技术文化为什么难写?
- 【Xmy的第一次Python】
- Java实现UDP组播(multicast)和单播(unicast)简单例子——局域网内
- a non-fatal error occured whilst loading database modules
- Springboot 整合百度地图 API