2012-04-13 38 views
12

在Java/Junit中,我需要使用某個對象測試null。有多種方法可以測試一個條件,但我一直在使用assertTrue來進行大多數測試。當我檢查assertTrue中的空值時,EclEmma聲明它只測試一個分支。當使用assertTrue而不是assertNull時缺少分支

當我手動將語句解析爲變量(如將結果設置爲布爾值並將其傳遞到assertTrue中)時,代碼覆蓋率在斷言中被認爲是完整的,但在變量初始化行上沒有。

這是怎麼發生的?這是否與在http://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions上提到的Java顯然增加的額外字節代碼有關?任何解決方案(除了使用其他斷言語句)。

assertTrue:

assertTrue(myObject == null); //1 of 2 branches 

assertTrue:

boolean test = (myObject == null); //1 of 2 branches missing 
assertTrue(test); // complete 

assertNull:

assertNull(myObject) //complete; 
+1

什麼是錯的使用assertNull斷言空?對所聲稱的東西使用適當的斷言類型通常會更好。如果測試失敗,您最好查看出了什麼問題,而不要在測試代碼中進行過多的挖掘。 – nansen 2012-04-13 18:23:48

+0

@nansen這是真的,我沒有問題,使用assertNull,如果它是一個要求,但是,IMO,所有斷言「類型」只是另一種形式的assertTrue。使用不同的斷言類型,如增加的錯誤信息/可讀性,可能會有額外的好處,但這不是真正的問題。 – 2012-04-13 18:30:26

+0

@nansen這並不是說我拒絕使用assertNull並且可能會使用它,我只是發現這個特殊的問題很有趣,因爲我基本上是在測試相同的東西,但Emma給出了完全不同的結果。 – 2012-04-13 18:31:24

回答

16

對於大多數布爾expressi Java編譯器會在字節碼中生成額外的分支。 JaCoCo基於生成的字節代碼生成「分支覆蓋」,而不是基於原始Java代碼,因此顯示您將使用的幾乎所有布爾表達式的附加分支覆蓋信息。

在您的代碼中,您使用的布爾表達式是myObject == null

爲了計算這個值,Java編譯器生成代碼推送堆棧上的兩個參數,然後執行條件跳轉以便在堆棧上推送1(真)或0(假)。 JaCoCo報道了該條件跳轉的分支機構報道。

因此,您使用myObject == null的事實會觸發您描述的行爲。

作爲一些其它實例中,嘗試:

boolean t = true; 
boolean f = false; 
boolean result1 = (t && f) || f; // 3 out of 6 missed. 
boolean result2 = !t;   // 1 out of 2 missed. 

如果布爾表達式爲,例如,由一個函數,這是在一個if-then-else語句用作條件返回這可能是有用別的地方。雖然大部分是Java編譯器工作方式的結果,但它有助於評估原始Java代碼的覆蓋範圍(而不僅僅是分支覆蓋範圍)。

這個功能是不是太有據可查的,但這裏有一些指針:

所以它確實與生成額外字節代碼有關,但不涉及打算使用過濾選項的合成字節編譯器結構的具體示例。

注意:從最初的答案以來主要的編輯是太多的猜測。感謝@ ira-baxter對於&的重要討論。

1

Emma將(條件表達式)作爲「有分支的東西」用於(分支)覆蓋範圍計數恕我直言的事實看起來很簡單。這不是一個有條件的分支。

我們可以爭論更多關於斷言;如果它被定義爲「在斷言失敗時拋出異常」,那麼它確實有一個條件分支;如果它被定義爲[因爲我認爲我做了,我不是Java專家]作爲「終止我的程序斷言失敗」,那麼它不是一個真正的分支。方法調用也很模糊;這些條件分支,因爲如果被調用的方法拋出異常,控制流不會繼續執行「語句的其餘部分」。

我們的Java Test Coverage工具獲得這些條件「正確」的(分支)覆蓋率分析。

+0

JUnit API中的assertTrue/assertNull方法沒有什麼特別之處。如果條件不成立,它們只會拋出java.lang.AssertionError。這與Java的'assert'關鍵字沒有直接關係。 – avandeursen 2012-04-15 07:07:50

+0

我同意調用這個Emma/JaCoCo特性*分支覆蓋*是(非常)混亂。 (分開)覆蓋信息告訴我任何布爾(子)表達式是否評估爲真和假是一個有用的功能,雖然。 – avandeursen 2012-04-15 07:11:02

+0

@avandeursen:確定程序中的每個*條件*是否被執行爲「真」或「假」不是分支覆蓋;它是「條件覆蓋」。當然,我們的工具不會做條件覆蓋;基於過去的理解,我不相信艾瑪確實會覆蓋覆蓋範圍,但我可能會感到驚訝。 – 2012-04-15 08:08:20

0

要在布爾方法得到100%的代碼覆蓋率,請執行下列操作

Class RecordService{ 


    public boolean doesRecordExist(String id){ 

    return id!=null; 

    } 


    } 

    //Method inside your mock 
    @Test 
    public boolean testDoesRecordExist(){ 
    RecordService recordService = mock(RecordService.class); 
    when(recordService.doesRecordExists()).thenReturn(
        anyString()).thenReturn(null); 

    }