2012-05-15 57 views
3

以下代碼中的switch語句具有default子句,該子句是編譯器所需的,並且是一個很好的保護措施,但從不執行。在爲其他事情編寫測試之後,我無法(或應該)測試那一行。我不在乎我沒有在測試中覆蓋該行,但是我的TestDriven.net NCover代碼覆蓋率報告確實顯示了未測試的行,這導致類覆蓋率下降到86%。有沒有辦法讓NCover排除這一行?NCover:從覆蓋範圍中排除不可執行的代碼行

public static class OperandTypeExtensions 
{ 
    public static string ToShortName(this OperandType type) 
    { 
     #region Contract 
     Contract.Requires<InvalidEnumArgumentException>(Enum.IsDefined(typeof(OperandType), type)); 
     #endregion 

     switch (type) 
     { 
      case OperandType.None: return "<none>"; 
      case OperandType.Int32: return "i32"; 
      case OperandType.Int64: return "i64"; 
      default: 
       throw new NotSupportedException(); 
     } 
    } 
} 

我的問題是類似this question,但沒有答案在我的具體情況提供幫助。

回答

2

您可以通過鑄造整數值,這是不是在OperandType枚舉存在於OperandType鍛鍊吧:

Assert.Throws<InvalidEnumArgumentException>(delegate { ((OperandType)Int32.MaxValue).ToShortName(); }); 

BTW我看沒什麼不好的,86%的覆蓋率

UPDATE:沒有的好處在這裏使用Contract。無論如何,如果您的方法不支持值,您將會得到例外。

public static class OperandTypeExtensions 
{ 
    public static string ToShortName(this OperandType type) 
    { 
     switch (type) 
     { 
      case OperandType.None: return "<none>"; 
      case OperandType.Int32: return "i32"; 
      case OperandType.Int64: return "i64"; 
      default: 
       throw new NotSupportedException(); 
     } 
    } 
} 

如果您還有這裏default的選擇,因爲如果新的價值將被添加到OperandType枚舉,您Contract將允許值,但開關不會支持新的選項。

UPDATE2:如果你真的需要100%的覆蓋範圍和合同這種方法,然後用OperandType.None作爲默認選項:

public static class OperandTypeExtensions 
{ 
    public static string ToShortName(this OperandType type) 
    { 
     Contract.Requires<InvalidEnumArgumentException>(Enum.IsDefined(typeof(OperandType), type)); 

     switch (type) 
     { 
      case OperandType.Int32: return "i32"; 
      case OperandType.Int64: return "i64"; 
      default: 
       return "<none>"; 
     } 
    } 
} 

並添加到您的測試斷言約枚舉:

CollectionAssert.AreEquivalent(Enum.GetValues(typeof(OperandType)), 
           new OperandType[] { OperandType.Int32, 
                OperandType.Int64, 
                OperandType.None }); 
+0

我不能這樣做,因爲合同會阻止我在OperandType枚舉中未定義的方法中賦予任何值,這是它應該是的。我會得到一個'InvalidEnumArgumentException'並且該行還沒有被覆蓋。 – Virtlink

+0

確切地說,我應該有'默認',作爲保障(如上所述)。合同肯定有一個好處:靜態檢查器可以驗證沒有人試圖在方法中放入一個未定義的值,並且它增加了該類型的文檔。 (沒有在參數上指定'Contract'約束就像使所有參數都是'object'類型)。 – Virtlink

+0

我認爲這是矯枉過正。如果期望'OperandType'的參數,誰會傳遞與您的方法不同的東西? –

-1

我也希望所有源文件都達到100%,而不是%,但是爲了避免每次運行代碼覆蓋率工具進行誤判時都要重複檢查每個類。

在這種情況下和國際海事組織,如果功能是公共這意味着你應類似測試

Assert.Throws<NotSupportedException>(OperandTypeExtensions.ToShortName()); 

的其他情況下可能發生

通常,如果函數throws或發生更大的問題是私人的。在這種情況下,有時線路不能通過測試達到。或者不能封裝在Assert.Throws中。

我發現確保每條線都被執行的唯一途徑。 遠離理想和非常醜陋,我會優先comment annotation like that來禁用它。雖然沒有在C#中工作。

private string ToShortName(this OperandType type) 
{ 
    var result = ""; 
    switch (type) 
    { 
     case OperandType.Int32: result = "i32"; 
     case OperandType.Int64: result = "i64"; 
    } 
    Debug.Assert(result != "", "Invalid type."); 
    return result; 
} 

通過這一解決方案,在源代碼將返回空字符串(在調試)和代碼覆蓋率將看到Debug.Assert的行執行之前打破。

P.S.雖然,我想知道是否有更好的解決方案,如註釋或某些特定的代碼塊禁用。

相關問題