Change Impact Analysis for Object-Oriented Programs

1. 介绍

变更影响分析(change impact analysis)提供了对一系列程序变更的语义影响的反馈。

这篇文章针对面向对象编程语言进行分析,小的变更会有意想不到的结果:如,向现有类添加方法会影响整个程序虚拟方法的调用

本文的方法:

  1. 将源代码的变更映射到一组原子变更(使用类、方法、域和它们的相互关系作为变更的原子单元)
  2. 此外还确定了这些原子变更的偏序关系,这些变更间的偏序关系保证程序句法合法
  3. 给定一系列原子变更 A \mathcal{A} 和给定的测试驱动集合 T \mathcal{T} ,执行程序的部分功能

静态分析来确定:

  • 测试驱动 T \mathcal{T} 中挑选被变更 A \mathcal{A} 影响子集 T \mathcal{T'} 用于回归测试
  • 变更集合 A \mathcal{A} 的子集 A \mathcal{A'} 可能影响 T \mathcal{T} 中的某些测试驱动 t \mathcal{t} 。这允许开发者忽略不被测试 t \mathcal{t} 失败影响的变更
  • 变更 A \mathcal{A} 的子集可能不影响任何测试用例,这些变更可以立即纳入
  • 覆盖率信息可以作为创建新测试用例的基础

2. 动机样例

贴了一页论文(-_-|||,太长不看)

该样例包含5个类:Course, Person, Professor, Student和University

然后有3个测试驱动:

  • TestA:找到特定教授打印TA教授的课
  • TestB:打印大学所有人员
  • TestC:找到特定学生打印其学分

然后就是说了三个方面的对于代码的变更

3. 变更

规定源程序为 P P ,修改后的程序为 P \mathcal{P'} ,他们都语法正确且可编译。

3.1 原子变更

方法的一个关键是将源代码的编辑转换为一组原子变化

QQ截图20181225150436.png

这些原子变更有两个重要特征:

  1. 粒度与分析内容相符合,也就是说,如果用了更细粒度的原子变更概念,分析也不会产生更精确的结果
  2. 任何源代码的编辑可以分解为唯一的原子变更集合

CM捕获对方法体的任意改变,包括:

  1. 在之前的抽象方法中添加方法体
  2. 从非抽象方法中删除方法体,让它抽象
  3. 方法体中任何语句级别的变更

LC类别对影响动态dispatch行为的源代码变更进行抽象,它可能由添加或删除方法,添加或删除集成关系导致。

change impact analysis 会忽略某些类型的源代码级别的变更,这些变更除了控制可见性外没有语义影响,如修改类/方法/域的修饰符,增删注释和增删import语句。

3.2 影响方法dispatch的变更

方法dispatch可能受多种编辑影响,我们使用 l o o k u p lookup 形式化方法dispatch过程。 l o o k u p lookup 接受两个参数:运行时类型和静态方法调用,返回通过virtual dispatch机制调用的方法定义

3.3 对原子变更排序

变更可能收到语法和语义上的其他变化。本文仅考虑必须满足的语法依赖性以保证可编译。语法依赖的例子有不能扩展未定义的类,或调用为定义的方法。语义依赖的例子是新增方法 m m 仅在存在被调用的方法 m m' 的改编版本时才表现出正确的行为。

使用原子变更上的偏序关系 \prec 表示语法依赖(同时也定义了传递闭包 \preceq^* ), \prec 定义了 A \mathcal{A} consistent子集 A \mathcal{A'} ,使得 A \mathcal{A'} 应用到 P P 的结果是合法的程序 P P''

A \mathcal{A'} 是consistent满足的条件:
a A  such that  a a , a A a A \forall a'\in A\text{ such that }a'\preceq^*a, a\in A'\Rightarrow a'\in A'
计算这些东西需要确定原子变更中引用的程序片段的语法要求

3.4 导出原子变更

将源代码编辑分解为原子变更是很简单直接的,文章由于篇幅原因只通过一个例子展示过程

4. 变更影响分析

程序 P P 有一些列测试驱动 T = t 1 , , t n \mathcal{T}=t_1, \dots, t_n N o d e s ( P , t i ) Nodes(P, t_i) 表示程序 P P 执行测试驱动 t i t_i 经过的方法结点, E d g e s ( P , t i ) Edges(P,t_i) 为调用关系。方法间的调用关系可以形式化地表示为: A . m C B . n A.m\rightarrow_CB.n ,表示 A . m A.m 通过类型 C C 对象的方法 n n 调用了方法 B . m B.m

QQ截图20181225165339.png

A f f e c t e d T e s t s ( T , A ) \mathit{AffectedTests(\mathcal{T}, \mathcal{A})} A f f e c t e d C h a n g e s ( t , A ) \mathit{AffectedChanges(\mathcal{t}, \mathcal{A})} 可以用来回归测试和故障定位,具体方法如下:

  • 任何不在 A f f e c t e d T e s t s ( T , A ) \mathit{AffectedTests(\mathcal{T}, \mathcal{A})} 中的测试驱动在 A \mathcal{A} 前后必定产生相同执行结果,所以只需要重新运行 A f f e c t e d T e s t s \mathit{AffectedTests} 中受影响的测试驱动就行
  • A f f e c t e d C h a n g e s ( t , A ) \mathit{AffectedChanges(\mathcal{t}, \mathcal{A})} 可以识别没有影响任何测试驱动的改变,这些改变可以安全的包含(纳入)。有时候这样的改变也是暗示缺少了测试用例
  • A f f e c t e d C h a n g e s ( t , A ) \mathit{AffectedChanges(\mathcal{t}, \mathcal{A})} 可以在测试失败时提供有用的信息

7. 未来工作

  1. 从源代码编辑中导出原子变化
  2. 计算原子变更间的序

猜你喜欢

转载自blog.csdn.net/u014578266/article/details/89042449
今日推荐