2011-11-24 19 views
0

我想測試以下兩種(無關)的方法和使用OpenCover 2.0.802.1我將如何獲得完整的OpenCover分支機構覆蓋這些代碼示例?

public class Methods 
{ 
    public static void MethodWithDelegate(SynchronizationContext context) 
    { 
     context.Send(delegate { Console.Beep(); }, null); 
    } 

    public static string MethodWithSwitchStatement(Type value) 
    { 
     string output = string.Empty; 

     if (value != null) 
     { 
      switch (value.ToString()) 
      { 
       case "System.Int32": 
        output = "int"; 
        break; 
       default: 
        output = "other type"; 
        break; 
      } 
     } 

     return output; 
    } 
} 

我寫了下面的(NUnit的)的測試中,一個用「起訂量」模擬對象實現全面分支和語句覆蓋:

[Test] 
public void Test_ShouldCoverMethodWithDelegate() 
{ 
    var context = new Mock<SynchronizationContext>(); 

    Methods.MethodWithDelegate(context.Object); 

    context.Verify(x => x.Send(It.IsAny<SendOrPostCallback>(), It.IsAny<object>())); 
} 

[Test] 
public void Test_ShouldCoverSwitchStatement() 
{ 
    Assert.That(Methods.MethodWithSwitchStatement(null), Is.EqualTo(string.Empty)); 
    Assert.That(Methods.MethodWithSwitchStatement(typeof(int)), Is.EqualTo("int")); 
    Assert.That(Methods.MethodWithSwitchStatement(typeof(float)), Is.EqualTo("other type")); 
} 

然而,通過OpenCover運行測試後,coverage.xml文件總是包含一個帶有兩個測試零訪問計數的分支點。序列覆蓋顯示100%。

不是一位IL專家,我不確定我會怎麼去編寫進一步的測試來使分支覆蓋率達到100%。

回答

2

好先讓我們來看看在IL第一種方法(我用IL SPY

.method public hidebysig static 
void MethodWithDelegate (
    class [mscorlib]System.Threading.SynchronizationContext context 
) cil managed 
{ 
// Method begins at RVA 0x2059 
// Code size 41 (0x29) 
.maxstack 8 

IL_0000: nop 
IL_0001: ldarg.0 
IL_0002: ldsfld class [mscorlib]System.Threading.SendOrPostCallback so8254847.Methods::'CS$<>9__CachedAnonymousMethodDelegate1' 
IL_0007: brtrue.s IL_001c 

IL_0009: ldnull 
IL_000a: ldftn void so8254847.Methods::'<MethodWithDelegate>b__0'(object) 
IL_0010: newobj instance void [mscorlib]System.Threading.SendOrPostCallback::.ctor(object, native int) 
IL_0015: stsfld class [mscorlib]System.Threading.SendOrPostCallback so8254847.Methods::'CS$<>9__CachedAnonymousMethodDelegate1' 
IL_001a: br.s IL_001c 

IL_001c: ldsfld class [mscorlib]System.Threading.SendOrPostCallback so8254847.Methods::'CS$<>9__CachedAnonymousMethodDelegate1' 
IL_0021: ldnull 
IL_0022: callvirt instance void [mscorlib]System.Threading.SynchronizationContext::Send(class [mscorlib]System.Threading.SendOrPostCallback, object) 
IL_0027: nop 
IL_0028: ret 
} // end of method Methods::MethodWithDelegate 

正如你可以看到有在IL_0007僅如果緩存的匿名委託已設置被執行的條件分支否則它會通過設置代理的主代碼然後調用它。

解決方案:運行測試兩次 - 或者忘掉它,因爲它是一個有點.NET優化現在

對於第二個問題這時候最好是看看在C#中實際製作 - 你寫開關聲明,但編譯器採用了IFS代替

public static string MethodWithSwitchStatement(Type value) 
{ 
    string output = string.Empty; 
    if (value != null) 
    { 
     string a; 
     if ((a = value.ToString()) != null && a == "System.Int32") 
     { 
      output = "int"; 
     } 
     else 
     { 
      output = "other type"; 
     } 
    } 
    return output; 
} 

正如你所看到的編譯器已經推出瞭如果與switch語句空測試,但是因爲你已經有這個已經那麼它將永遠不會被執行。

解決方案:刪除您的初始if null測試(因爲它不是必需的)。

+0

有趣的...非常感謝您的答案 - 和OpenCover也是,太棒了! –

+0

不客氣 - 我也做了一篇關於序列報道的文章,以及你可能會覺得有用的http://scubamunki.blogspot.com/2011/08/problem-with-sequence-coverage.html –

+0

好文章, ReportGenerator不支持(但)完全支持分支覆蓋的顯示是一件令人遺憾的事情。在瀏覽coverage.xml文件時,我發現上面提到的'問題'。 –

相關問題