NCover:从coverage中排除不可执行的代码行

时间:2012-05-15 15:12:07

标签: c# unit-testing code-coverage ncover

以下代码中的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();
        }
    }
}

我的问题类似于this question,但没有一个答案有助于我的具体情况。

2 个答案:

答案 0 :(得分:2)

您可以通过将OperandType枚举中不存在的整数值转换为OperandType来执行此操作:

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

BTW我认为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将允许该值,但切换将不支持新选项。< / p>

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 });

答案 1 :(得分:-1)

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

在这种情况下和IMO,如果功能是公开的,则意味着你应该用类似的东西测试

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

可能发生的其他情况

通常,当throwsDebug.Assert为私有的函数时,会出现更大的问题。在这种情况下,有时测试无法到达线条。或者无法封装在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中),Code Coverage将看到Debug.Assert行被执行。

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