3

以下代码中的 switch 语句有一个default编译器需要的子句和一个很好的保护措施,但它永远不会被执行。在为其他所有内容编写测试之后,我无法(或应该)测试那一行。我不在乎我没有用测试覆盖这条线,但我的 TestDriven.net NCover 代码覆盖率报告确实显示了未经测试的线,这导致类覆盖率下降到 86%。有没有办法让 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();
        }
    }
}

我的问题与这个问题类似,但没有一个答案对我的具体情况有帮助。

4

2 回答 2

3

您可以通过将 OperandType 枚举中不存在的整数值转换为 OperandType 来练习它:

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

顺便说一句,我认为 86% 的覆盖率没什么不好

更新:在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将允许该值,但 switch 将不支持新选项。

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 });
于 2012-05-15T15:15:58.500 回答
-1

我还希望我的所有源文件都达到 100%,而不是为了 %,而是为了避免每次运行代码覆盖率工具时都对每个类进行双重检查以发现误报。

在这种情况下和 IMO 中,如果该功能是公开的,则意味着您应该使用类似的东西对其进行测试:

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

其他可能发生的情况

通常,当函数中的throws或函数Debug.Assert是私有的时,会出现更大的问题。在这种情况下,有时测试无法到达这些线路。或者不能封装在Assert.Throws.

我发现确保执行每一行的唯一方法。远非理想且非常丑陋,我更喜欢这样的注释注释来禁用它。虽然在 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 中)之前中断,并且 Code Coverage 将看到 Debug.Assert 行已执行。

PS虽然,我想知道是否有更好的解决方案,比如注释或专门禁用代码块的东西。

于 2014-01-23T22:50:09.587 回答