什么是未被覆盖的区块?

3

Visual Studio 2013 在显示此对象的代码覆盖率时(为了简化此示例),缺少一个块:

code coverage

据我所知,那个 if 应该有两种状态。通过和失败。而调试我的测试表明,每个条件都被执行一次。具体来说,这两个测试如下:

[TestMethod]
public void CanNotHaveNegativeServiceWindow()
{
    // arrange
    var request = new CreateCaseRequest
    {
        ServiceWindowStart = new DateTime(2014, 12, 31, 12, 00, 00),
        ServiceWindowEnd = new DateTime(2014, 12, 31, 11, 00, 00)
    };

    // act
    var result = request.GetValidationErrors();

    // assert
    Assert.AreEqual(1, result.Count());
}

[TestMethod]
public void CanHaveServiceWindow()
{
    // arrange
    var request = new CreateCaseRequest
    {
        ServiceWindowStart = new DateTime(2014, 12, 31, 11, 00, 00),
        ServiceWindowEnd = new DateTime(2014, 12, 31, 12, 00, 00)
    };

    // act
    var result = request.GetValidationErrors();

    // assert
    Assert.AreEqual(0, result.Count());
}

有一个测试验证了特定的 if 条件的正结果,另一个测试验证了负结果。那么哪个块没有被覆盖?我是否遗漏了某个逻辑条件?


如果它们是null或者相等怎么办? - Daniel A. White
@DanielA.White:其他测试覆盖了那些情况。只有在它们都有值的情况下才会到达那个if。如果它们都相等,那么这就是if的错误条件,不是吗?也就是说,与任何其他错误条件没有区别? - David
我明白你想要做什么(我删掉了我的旧评论)。你可以尝试使用if (ServiceWindowStart.Value > ServiceWindowEnd.Value)吗? - Sergey Kalinichenko
@dasblinkenlight:非常有趣,看起来这似乎解决了问题。我猜编译器在比较“Nullable<T>”时会创建一些额外的块。逻辑上,我已经覆盖了这些情况,但编译器对于特定的比较并不知道。请继续添加为答案,谢谢! - David
2个回答

3
当您比较Nullable<T>值时,C#编译器会创建额外的检查来确保Nullable<T>有值。这些检查在您的代码中始终以相同的方式进行,因为您已经明确执行了所有的null检查。
将条件更改为
if (ServiceWindowStart.Value > ServiceWindowEnd.Value)

应该解决这个问题。

Gaaaaaaaaaaaaaa!在这上面浪费了3个小时。我的代码在一个自定义比较器中。 /* x和y是相同的类型 */ 如果(x.MyNullableDate.HasValue && y.MyNullableDate.HasValue && x.MyNullableDate == y.MyNullableDate) 我知道我通过单元测试覆盖了每个排列组合。添加.Value到两个...修复了覆盖范围。谢谢。 如果(x.MyNullableDate.HasValue && y.MyNullableDate.HasValue && x.MyNullableDate.Value == y.MyNullableDate.Value) - granadaCoder

2
浅米色并不意味着代码没有被覆盖。它意味着只有部分被覆盖了。您的ServiceWindowStart和ServiceWindowEnd可以为null。但是,您只使用值来测试它们。并且您并没有测试它们是否相等。添加对空值和相等情况的测试应该可以解决缺失的测试用例。
这种结果出现的另一个可能原因与代码覆盖率是在IL代码上执行而不是在C#代码上执行有关。并且IL的等效物可能没有完全被覆盖或代码结构可能没有被保留。
优化您的构建可能会解决此问题。转到"解决方案资源管理器" -> "属性" -> "生成"选项卡 -> 选中"优化代码"复选框。
选择此选项后运行代码分析。
这篇有趣的博客文章涵盖了这个话题:http://blogs.msdn.com/b/ddietric/archive/2009/10/21/all-the-wonderful-colors-of-code-coverage.aspx

其他测试(未在此处显示)涵盖了null值。此外,如果任一值为null,则if (ServiceWindowStart.HasValue && ServiceWindowEnd.HasValue)会防止流程进入该块。所讨论的if条件仅适用于两个值都不是null的情况。我知道它部分被覆盖了,但我看不到哪一部分没有被覆盖。 - David
你也测试了相等的情况吗?另外,当一个值为空而另一个值不为空时,还考虑了加法选项吗? - PiotrWolkowski
我刚刚添加了一个测试相等值的测试,结果相同。这并不让我感到惊讶,因为两个相等的值与两个不相等但小于的值进行>比较将具有相同的结果。是的,在其他测试中我确实会测试null值。但那些并不相关,因为如果任何一个值为null,则在问题之前的if条件将永远不会被满足。那是完全不同的逻辑分支。 - David
尝试优化你的代码。我在我的答案中添加了指令。 - PiotrWolkowski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接