2010-09-15 102 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

相關問題