2010-09-15 56 views
7

我正在使用EclEmma进行覆盖率分析。EclEmma为什么不包含syncronized(MyClass.class)?

我的Java代码包含一个同步的(MyClass.class){}块。

EclEmma说它只是部分覆盖,事件虽然我有一个单元测试,其中一个线程访问和另一个线程被阻止。

是否有可能使用EclEmma完全覆盖同步?

我可以通过某种方式注释代码来告诉EclEmma为此行提供全面覆盖吗?

亲切的问候 罗杰

回答

6

我不知道这是可能得到一个全覆盖,因为issue 2939804报道:

EMMA总是标志着synchronized(..)部分覆盖

例子:

synchronized (lock) // partially covered (yellow line in EclEmma) 
{ 
// ... 
} 
synchronized (this) // partially covered (yellow line in EclEmma) 
{ 
// ... 
} 

也许一个不同的工具(like Cobertura)会产生不同的结果? (我最近没有测试过)。


2012更新腊(超过2年后):

Nathan D Ryanreports

​​将点亮为绿色,如果同步块包含一个对象监视器上等待代码,和测试会中断等待的线程。

经过一些实验后,如果​​块正常完成并由于异常突然完成,我能够实现​​行的完整覆盖。

+0

看起来你是对的。我试过这个:Object synch = MyClass.class; synchronized(synch){}但它没有帮助,即使我的测试有一个线程正在等待,另一个线程正在获取互斥体。 – 2010-09-15 08:00:24

+2

根据我的经验,如果同步块包含在对象监视器上等待的代码,并且测试会中断等待的线程,则'synchronized'将点亮为绿色。不过,我从来没有打算深入EMMA的仪器,以确定在一般情况下是否属实。 – 2012-12-13 23:17:52

+1

经过一些实验后,如果同步块正常完成*和*由于异常突然完成,我能够实现'synchronized'行的完全覆盖。 – 2012-12-14 00:41:44

0

我相信问题是MyClass.class这显然是利用

http://emma.sourceforge.net/faq.html#q.fractional.examples

隐分支由于隐藏的Class.forName()实现。这种情况是 相当不幸,因为它很常见,但程序员 几乎没有控制它。

因为Class.forName()可以抛出检查异常,所以编译器 会发出一个catch块,将其重新抛出为未选中状态。该捕捉块 在实践中很难执行,但它成功地将行 标记为部分覆盖。

我错过了第一次阅读。

我会尝试重写我的代码以获得全面覆盖。

/Roger

1

EclEmma使用下面的Jacoco进行覆盖率分析。

正如上文Jacoco的(目前不存在的)JAVAC.SYNC filtering option,该行为是用于同步的块中产生的字节代码的结果是:

一个Java同步块被编译成两个字节码指令:在所述MONITORENTER在块的结尾处开始和MONITOREXIT。

为了确保监视器在任何情况下都被释放,安装了一个指向另一个MONITOREXIT指令的异常处理程序。这个异常处理程序块通常会导致部分行覆盖,这从源代码的角度来看是没有意义的。

一个相关Jacoco issue 245解释的异常如何被触发,达到全覆盖,应该有这样的需要,同样通过@森 - 莱恩解释说:

  1. 一个测试,通常执行synchronized块
  2. 第二个测试从同步块内抛出(并因此期待)异常。
+1

(Hi Arie)。所以Jacoco并不理解控制流是安全的*:如果你到达了入口点,你将会*到达出口点。我想象一个带有局部变量的块被编译成一个块,它初始化本地,执行主体并清理本地,并且在块的周围包裹一个额外的隐式异常处理程序,以便在发生异常时清理本地。这在风格上看起来完全一样;但你可以通过“执行”来完全覆盖一个块。 (我们的Java测试覆盖工具可以测试源代码,不会混淆)。 – 2016-06-01 12:46:49

相关问题