测试套件生成(针对整个套件)
www.fireknight.tech 个人博客,欢迎访问,CSDN不定期更新
-
要点:测试套件生成、遗传算法、选择、变异
-
总结
- 给出了一个生成测试套件的方法,能生成更小的测试套件并且有更高的分支覆盖率(方法已经全覆盖)
- 定义了遗传算法适应度函数:主要是对分支距离的计算
- 定义了遗传算法的操作:测试套件级别交叉,测试用例内的变异
- 防止遗传算法膨胀,给出了四个限制
-
abstract
- 提出了一种生成测试套件**(test suit)**的方法,能够覆盖所有的coverage goals同时尽可能的小
-
Intro
-
oracle problem
- 运行一个测试,除了结果比对之外,无法知道测试是否执行正确,因为还有崩溃、异常执行等问题,必须人工检查。这就是自动化测试的缺陷 – oracle problem
- 所以测试套件要尽可能的小,方便测试人员人工比对。
-
背景问题 - 传统方法:为每个分支(目标)生成测试套件
- 为每个目标生成测试用例,然后组合成测试套件。导致整体测试套件很大。同时测试目标之间互相关联,比如push和pop
- 为每个目标生成测试用例,有些分支无法覆盖(诸如死分支)。在这些分支上回消耗更多的时间
-
整体测试套件test suit生成
-
同时为所有目标生成整个测试套件。
- 适应度函数考虑所有目标
- 随机生成初始测试套件组 test suits
- 遗传算法
- 次要目标为套件大小
-
实现了EVOSUITE工具
-
不可行分支对没有性能影响
-
-
-
背景
-
通过符号或基于搜索的方法生成测试输入
-
符号执行解决约束 – DART/CUTE
-
Solving path constraints generated with symbolic execution is a popular approach to generate test data [50] or unit tests [51], and dynamic symbolic execution as an extension can overcome a number of problems by combining concrete executions with symbolic execution (e.g., [22], [39]). This idea has been implemented in tools like DART [22] and CUTE [39], and is also applied in Microsoft s parametrized unit testing tool PEX [42] or in the Dsc [28] tool
-
-
元启发式替代符号搜索
-
当前方法问题:
- 测试套件目标单一
-
目标
- Satisfy the chosen coverage criterion (e.g., branch coverage) with the smallest possible test suite.
-
-
测试套件优化
-
遗传算法
- 略
-
符号表示
-
一个test suit – 目标
-
表示为集合T,由一组test case ti组成
Given |T| = n, we have T = {t1,t2, . . . ,tn}.
-
一个test case由一组语句组成
- t = <s1,s2, . . . ,si>, lengh l
-
每个语句表示一个值 v(si), 有一个对应的类型 τ(v(si))∈T, T是一个有限集合组
-
语句类型定义为如下
-
Primitive statements
- int var0 = 54
-
构造语句/实例化
- stack var2 = new stack()
- [Q] 任何构造参数被赋值于{v(sk) | 0 ≤ k < i}外的值
-
变量语句 - 获取变量
- int var3 = var2.size
- filed的source object应该是在集合{v(sk) | 0 ≤ k < i}中
-
方法语句
- int var4 = var2.pop()
- source object要求如上一个
-
赋值语句
- var2.maxsize = 10
-
-
For a given SUT, the test cluster [47] defines the set of
available classes, their public constructors, methods, and fields. – 基本元素的可知的
-
-
需要先定义 N(测试套件中的测试数), L(一个测试的长度)
-
-
适应度函数
-
focus on: 分支覆盖率
-
符号
-
B:分支,To:最合格解
-
MT: 执行了的方法(不含分支), M总方法(不含分支)
-
dmin(b,T): 最小分支距离,到达另一个分支的距离
- if判断x>10, x=5, 分支距离(到true)为 10-5+k(k>0)
-
-
如果两个测试套件有相同的覆盖率,则选中更少的
-
总适应度函数:
-
-
待执行方法适应度+待执行分支适应度
-
-
分支距离部分:
-
-
通过分支的次数越多,越有可能覆盖所有情况。覆盖true,false至少两次,所以覆盖一次取0,两次取距离,其余取1
-
v: normalze to [0, 1]
- 一个分支预测d(b,T)。如果自己没覆盖,则d(b,T)>0, d(bopp,T)=0。分支会向d(b, T)偏移,导致d(b,T)=0, d(bopp,T)>0。又向最初情况偏移。归一化防止这种情况
-
-
-
膨胀控制
-
多目标容易出现这种情况:测试数量越来越多
-
具体方法
-
N和L的限制
- 给限制,但尽量给大的值。这样可以生成较覆盖率较好的测试但最后又会选择出较短的测试
-
rank selection based on fitness function
- 方法覆盖率 然后 分支距离
- 短的测试有更高的等级
-
子代覆盖率相比父代更低且长度更长,则这样的子代永远不会选择
-
子代的覆盖率没有优于最佳方案TB,那么如果它的长度超过TB的两倍,那么它在新一代中就不会被接受
-
-
-
具体操作
-
交叉变异
-
测试套件级别的交叉,测试用例级别的变异
-
-
交叉
-
p1的a%+p2的(1-a%) p父类
-
优点
- 子代必有效
- 两个子代长度差小于父代长度差
-
-
变异 套件和个体变异同时发生
-
一个套件T中,每个测试以1/|T|的概率变异,这样大致共有一个测试变异
-
以概率σ, σ2…以此加入新的测试,直到没加入或者总数大于N
-
测试套件变异 移除、改变、插入 – 1/3概率执行
- 具体规则略,和测试生成的约束条件强相关
-
-
初始种群生成
- 随机生成
-
算法代码
-
-
-
EVOSUITE TOOL – 具体实现
- 在字节码级别上工作,并通过Java Reflection从字节码中收集测试集群的所有必要信息
- 变量特殊处理进行距离计算
- 测试生成时,每次只考虑一个top-level类
- 测试用例超时处理
- 防止内存耗尽,客户机/服务架构,监控内存/重启进程
- 对访问文件等资源的安全处理
- Single Branch Strategy:设计的对比方案(模拟别的生成方法)
-
EXPERIMENTS
-
结果
- Whole test suite generation achieves higher coverage
than single branch test case generation - Whole test suite generation produces smaller test suites
than single branch test case generation.
- Whole test suite generation achieves higher coverage
-
难以到达的分支分析
- 环境依赖、匿名方法、多线程等
-