MSTest在复合布尔表达式上显示部分代码覆盖率

12

根据微软的文档,部分覆盖代码是指"...在一行中一些代码块未被执行。" 简单来说就是:

给定以下方法:

public List<string> CodeUnderTest()
{
    var collection = new List<string> { "test1", "test2", "test3" };
    return collection.Where(x => x.StartsWith("t") && x == "test2").ToList();
}

And this test:

[TestMethod]
public void Test()
{
    var result = new Class1().CodeUnderTest();
    CollectionAssert.Contains(result, "test2");
}

代码覆盖率结果显示,表达式x.StartsWith("t") && x == "test2"只被部分覆盖。我不确定这是如何可能的,除非编译器或CLR有一些急切的条件匹配机制,但也许我只需要解释一下。

值得注意的是,使用 || 与多个布尔条件也是一样的。 - lukiffer
当然,使用 || 是有意义的,但是使用 && 就没有意义了——如果 && 语句评估为 true,它怎么可能跳过任何条件呢?我现在遇到了这个问题,感觉很疯狂。完全没有意义。 - BrainSlugs83
1个回答

15
条件与运算符(&&)对其布尔操作数执行逻辑AND运算,但仅在必要时评估其第二个操作数。

http://msdn.microsoft.com/en-us/library/2a723cdk(v=vs.100).aspx

所以你期望两个方面都被涵盖

也许它抱怨的是你没有测试负路径,即如果你的集合为空

var collection = new List<string> { "test1", "test2", "test3", "not_this_one" };

这样你就可以测试x.StartsWith("t")的真假性,因为目前只有T路径被测试了该条件。


2
经过一些调查,当使用 && 时,似乎除非在给定 {A=true,B=false}(false)、{A=false,B=not evaluated}(false)和 {A=true,B=true}(true)的情况下测试代码,否则它不会认为代码完全覆盖。但只有当复合时才有效。如果单独给出 AB,无论它们是真还是假都没有关系。 - lukiffer
4
@lukiffer,你说得对。Visual Studio的覆盖率工具是通过基本块分析来实现的。基本上,每个基本块开头都有一个探针来记录在测试期间它是否被执行。对于像这样的语句,多个基本块映射到同一行。如果任何基本块未执行(例如,通过条件评估短路,正如你所注意到的那样),则该行将显示为部分覆盖。出处:我是覆盖工具的开发者,直到VS2012版本。 - Peter Huene
但是,如果A为真,B也为真--那么我编写的两个代码块都会被执行--(它必须评估它们两个,对吧?)--但你说我必须测试所有这样的组合,因为编译器生成的代码块?--似乎很疯狂,我不得不测试编译器生成的代码。 :-/ - BrainSlugs83
@BrainSlugs83 如果你想要完整的分支覆盖而不仅仅是语句覆盖,那么你可以这样做。 - Shaun Wilde
那么这个部分覆盖是如何实现的:if (x.Collection != null && x.Collection.Count != 0) { },而这个完全覆盖是:if (x.Collection != null) if (x.Collection.Count != 0) { },使用相同的测试集。 - Wouter

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