本文共 2314 字,大约阅读时间需要 7 分钟。
自从上一篇博客 以来,很久没有再写相关的内容了,今天再继续一篇,呵呵!我们知道,根据覆盖度量单元的不同,代码覆盖可以分为很多种,如:语句覆盖、判定覆盖、条件覆盖、路径覆盖等等,Visual Studio(2005,2008 和 2010)系列工具中所采用的是语句覆盖(statement coverage),也被称为block coverage。相对于其它覆盖而言,block覆盖操作和分析简单,是实际工程中比较常用的一种覆盖测试工具。那么究竟一个block是如何定义的呢? block与代码行之间存在着对应关系吗?先来看看下面一个例子:
首先,自定义一个简单的C#函数GetInteger() 作为接下来被测试和代码覆盖收集的对象:
然后, 针对这个GetInteger编写一个简单的单元测试用例,输入的数据组合为 (arg1=1, arg2=-1)
[TestMethod] public void GetIntegerTest() { Program target = new Program(); int expected = 0; int actual = target.GetInteger(1, -1); Assert.AreEqual(expected, actual); }
下面执行GetIntegerTest测试,看看这个用例到底覆盖了GetInteger中的哪些代码。执行的代码覆盖结果如下图所示:Visual Studio使用不同的颜色来区分不同的覆盖结果:
通过上面的米色未完全覆盖行 – if(arg1 >0 && arg2 < 0),我们可以看出同一行代码不一定属于同一个block,有可能一个代码行中包含了多个block。那么可不可以说同一个block的内容一定全在同一行上?要回答这个问题,我们可以先看一下Visual Studio到底将GetInteger划分几个block。
通过上面的Code Coverage窗口中显示的覆盖数据结果,可以看出GetInteger一共被划分为 2 + 5 = 7 个block,其中未覆盖的block有2个。很显然,米色未完全覆盖行中肯定包含一个未覆盖block,那么剩下的一个只能可能是下面的“{”行和“return 1;”行。也就是说,“{” 和 “return 1;”这两行被认为是一个block,所以说同一个block的内容不一定全在同一行上,它有可能是分布在多行上,如下图所示:
综上所述,block和代码行之间没有非常规律的对应关系。那么到底block是如何定义的呢? 给出了如下的定义:
A code block is a code path with a single entry point, a single exit point, and a set of instructions that are all run in sequence. A code block ends when it reaches a decision point such as a new conditional statement block, a function call, exception throw, enter, leave, try, catch, or a finally construct.
简单的说,就是有个单一入口和单一出口的代码块就被认为是一个block,但是这样的定义实际上是很难和代码直接对应上。之所以这样,是因为Visual Studio进行的instrument是针对IL或者(二进制)代码级别的而不是文本代码级别的。例如:GetInteger一共有7个block,能够直接从代码中识别出的有block (1,2,3,4),如下图所示。而block 5中实际上是包括3个block,我等凡夫俗子单凭肉眼是很难准确区分出这3个block的。
在一般的代码覆盖应用中,我们不必关心的block到底是如何定义和划分的,代码覆盖的核心用途是要发现已有测试所遗漏的产品代码,而这些被测试遗漏代码在“彩色”代码窗口已经可以很清楚地找到。如果要真想了解你的代码是如何被划分block,办法也是有的: 针对.NET语言,ildasm.exe就是这样的工具,用它来查看instrumented后的IL代码,并和未instrument的IL进行比较,你就会发现其中的奥秘。此时,对照着上面给出的code block的定义,可以更清晰地体会“单一入口和单一出口的代码块”的含义。在下一篇博客《》中,将会花些时间具体介绍。
参考内容
转载地址:http://twgki.baihongyu.com/