从Instrument的方式比较Emma与Clover

本文探讨了在代码覆盖率评估中,Emma与Clover两种工具在Instrumentation方式上的区别及其对覆盖率结果的影响。通过实例分析了两种工具在处理特定代码逻辑时的差异,强调了Emma在提供更精确覆盖度量方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载,地址:http://qa.taobao.com/?p=6425

从Instrument的方式比较Emma与Clover

2010年5月19日 由 yuanpu 留言 »

1 INTRODUCTION

最近在做与code coverage相关的工作,接触了一些code coverage 的知识。在这里与大家做个分享。下文主要是在Instrumentation的方式上,对Emma与Clover进行了比较,并且分析了由于Instrumentation方式上的不同而导致的coverage的结果不同的原因。
关于clover和emma,是两个大家都厂家的工具,这里就不多说了。仅给出链接,供详细了解。
Clover: http://www.atlassian.com/software/clover/
Emma: emma.sourceforge.net
注:本文所说的代码仅局限在Java代码上。
2 INSTRUMENTATION 方式介绍
在这一章中,我们大致的介绍一下Instrumentation的不同的方式。
为了获得code coverage measurement, 目前大致有三种Instrumentation的方式:
 源代码的Instrumentation(source code instrumentation): 这种方式在源代码上,直接进行Instrumentation. 然后将Instrument后的代码编译成.class 文件。
 中间代码的Instrumentation(Intermediate code instrumentatio): 这种方式是直接在编译后的.class文件是直接加入新的字节码。
 实时信息的获取( Runtime Information Collection):这种方式是在代码运行过程中收集动态的运行消息而决定coverage的信息。
目前Clover采用的是第一种方式(源代码的Instrumentation),而Emma采用的是第二种方式(中间代码的Instrumentation)。
3 CLOVER的INSTRUMENTATION 方式
在这一章中,我们将详细描述一下源代码的Instrumentation的原理。就拿图一的代码做个例子. (图一的代码功能及其简单,这里就不多说了)。

图一:before Instrumentation

我们再看看Instrument以后的代码(见图二)。



图二: After instrumentation


由图一和图二的对比,我们可以发现,在每一个method, statement和branch之前,都添加了一行代码。这行代码代表着是一个整形数的counter.
特别的,如果针对branch,我们要区分是“true”还是”false”的branch被执行了,所以做了特别的处理。如图二中所示,if 后的Boolean expression变成了
if ( ( data==0 && ++CT[338]!=0 | true ) || ( ++CF[338] == 0 & false ) )

 如果data==0是true, 那么 && 之后的部分也会执行。 这样CT[338]就会被增加一。而最后的“|true”是为了保证整个的boolean expression的值还是保证为”true”.
 如歌data==0是false,那么“||”之后的部分会被执行。这样CF[338]就会被增加一。而最后的“&false”是为了保证整个的boolean expression的值还是保证为”false”.
从以上的Instrument的方式,我们可以看出,每次在源代码中加入一个Counter, 我们都需要一个整形数(4 bytes)。 这样对于一个大型的项目,开销还是非常大的!
4 EMMA 的INSTRUMENTATION方式
至于Emma 的Instrumentation 的方式,可以参见图三。

图三:Instrumentation in Emma.

如图三所示,Emma通过对.class文件中的bytecode进行分析, 从而找出在.class文件中每一个basic block. 并且在每个basic block之后插入一个Probe(探针)。 这样每个probe被执行后,程序运行时coverage的信息也就被收集到了。
在这里每一个basic block是指一段没有保护任何跳转指令的bytecode 指令。 而每个probe是指一段用于记录某个basic block是否被运行的bytecode. 具体的每个probe包含以下四条指令(或者是类似这四条的指令):
1. ALOAD probearray #在emma 会在每个class中新建一个boolean的数组,用于记录每个basic block是否被执行。这行指令,就是把这个数组的引用加载进操作数栈
2. ICONST probeid #将某个probe的id, 加载进操作数栈
3. ICONST_1 #将常量”1”加载进操作数栈
4. BASTORE #将probearry[probeid] 的值改为1.
至于 emma的内存开销,主要也就是花费在每个class所开的boolean数组(1 byte per element)。 而这个数组的大小是这个class内的basic block的数量决定的。
5 不同INSTRUMENTATION 方式所得到的结果
那么由这两种不同的Instrumenetation方式得到的coverage的结果又会有什么不同呢。当然正常情况下,clover 和emma基本类似。但是遇到特别的情况就不一样了。
就拿下面的程序做个例子, 我们给coverageTest()的输入是0, 因此期望只执行” (a==0)? (data+1): (data+2);”中的一个分支
public static void main(String[] args) {
int a = 0;
coverageTest( a );
}
public static void coverageTest( int a ){
int data = 0;
a = (a==0)? (data+1): (data+2);
}
在clover 下运行的结果如下图所示,全部被覆盖:Line coverage: 100%

在emma下的结果如下图所示:

上图显示“(a==0)? (data+1): (data+2);”为黄色。这个在emma中表示的意思是这行代码没有全部被覆盖。特别的, line coverage为92% (2.8/3)。这个背后的原因是“(a==0)? (data+1): (data+2);”在byte code level被分成不同的basic block来处理。

6 结论
上文简单的就clover和emma的不同的instrumentation的方式进行了讨论,并且举例说明了不同的instrumentation方式对所得到coverage的准确度的影响。显而易见,emma是能更加准确的反应代码的覆盖情况的。
当然这两种Instrumentataion 方式还有很多不同,还没深入研究,这里就不敢多说了。
最后从Clover的官方网站上截取了一段话给大家看看:
Clover uses source code instrumentation, because although it requires developers to perform an instrumented build, source code instrumentation produces the most accurate coverage measurement for the least runtime performance overhead.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值