代码覆盖率教程:分支、语句和决策测试
什么是代码覆盖率?
代码覆盖率是一种度量指标,它描述了程序源代码被测试的程度。它是白盒测试的一种形式,用于查找程序中未被一组测试用例执行的区域。它还创建一些测试用例以增加覆盖率并确定代码覆盖率的量化度量。
在大多数情况下,代码覆盖率系统会收集有关运行程序的信息。它还将这些信息与源代码信息相结合,生成关于测试套件代码覆盖率的报告。
为什么要使用代码覆盖率测试?
以下是一些使用代码覆盖率的主要原因:
- 它有助于衡量测试实施的效率
- 它提供了量化度量。
- 它定义了源代码被测试的程度。
代码覆盖率方法
以下是主要的几种代码覆盖方法:
- 语句覆盖
- 决策覆盖
- 分支覆盖
- 翻转覆盖
- FSM 覆盖
语句覆盖
语句覆盖是一种白盒测试技术,其中源代码中所有可执行语句至少被执行一次。它用于计算已执行的源代码语句数量。语句覆盖的主要目的是覆盖源代码中所有可能的路径、行和语句。
语句覆盖用于根据被测代码的结构推导场景。
在白盒测试中,测试人员专注于软件的工作原理。换句话说,测试人员将专注于源代码与控制流图或流程图相关的内部工作。
通常在任何软件中,如果我们查看源代码,会有各种各样的元素,如运算符、函数、循环、异常处理程序等。根据程序的输入,一些代码语句可能不会被执行。语句覆盖的目标是覆盖代码中所有可能的路径、行和语句。
让我们通过一个示例来理解如何计算语句覆盖率。
计算给定源代码语句覆盖率的场景。这里我们采取两种不同的场景来检查每种场景的语句覆盖率百分比。
源代码
Prints (int a, int b) { ------------ Printsum is a function int result = a+ b; If (result> 0) Print ("Positive", result) Else Print ("Negative", result) } ----------- End of the source code
场景 1
如果 A = 3,B = 9黄色标记的语句是根据场景执行的语句
已执行语句数 = 5,总语句数 = 7
语句覆盖率:5/7 = 71%
同样,我们来看场景 2,
场景 2
如果 A = -3,B = -9
黄色标记的语句是根据场景执行的语句。
已执行语句数 = 6
总语句数 = 7
语句覆盖率:6/7 = 85%
但总的来说,如果两者都看,所有语句都已被两个场景覆盖。所以我们可以得出结论,总语句覆盖率是100%。
语句覆盖涵盖了哪些方面?
- 未使用的语句
- 死代码
- 未使用的分支
- 缺失的语句
决策覆盖测试
决策覆盖是一种白盒测试技术,它报告源代码中每个布尔表达式的真或假结果。决策覆盖测试的目标是通过检查和确保每个可能决策点的每个分支至少执行一次来覆盖和验证所有可访问的源代码。
在这种覆盖类型中,表达式可能变得复杂,使得实现100%覆盖具有挑战性。这就是为什么使用各种方法来报告这个度量。这些方法优先考虑最关键的组合。虽然它与决策覆盖相似,但它提供了对控制流更高的敏感度。
决策覆盖示例
考虑以下代码-
Demo(int a) { If (a> 5) a=a*3 Print (a) }
场景 1
a 的值为 2
黄色高亮显示的代码将被执行。这里检查决策 If (a>5) 的“否”结果。
决策覆盖率 = 50%
场景 2
a 的值为 6
黄色高亮显示的代码将被执行。这里检查决策 If (a>5) 的“是”结果。
决策覆盖率 = 50%
测试用例 | A 的值 | 输出 | 决策覆盖 |
---|---|---|---|
1 | 2 | 2 | 50% |
2 | 6 | 18 | 50% |
分支覆盖测试
分支覆盖是一种白盒测试方法,其中测试了代码模块(语句或循环)的每个结果。分支覆盖的目的是确保每个分支的每个决策条件至少执行一次。它有助于测量独立代码段的比例并找出没有分支的段。
例如,如果结果是二进制的,您需要测试真和假两种结果。
计算分支覆盖率的公式
分支覆盖示例
要学习分支覆盖,让我们考虑前面用过的相同示例
考虑以下代码-
Demo(int a) { If (a> 5) a=a*3 Print (a) }
分支覆盖也将考虑无条件分支
测试用例 | A 的值 | 输出 | 决策覆盖 | 分支覆盖 |
---|---|---|---|---|
1 | 2 | 2 | 50% | 33% |
2 | 6 | 18 | 50% | 67% |
分支覆盖的优点
分支覆盖测试具有以下优点:
- 允许您验证代码中的所有分支
- 帮助您确保没有分支导致程序操作的任何异常
- 分支覆盖方法消除了语句覆盖测试引起的问题
- 允许您找到其他测试方法未测试的区域
- 它允许您找到代码覆盖率的量化度量
- 分支覆盖忽略布尔表达式内部的分支
条件覆盖测试
条件覆盖或表达式覆盖是一种测试方法,用于测试和评估条件语句中的变量或子表达式。条件覆盖的目标是检查每个逻辑条件的各个结果。条件覆盖比决策覆盖提供更好的控制流敏感性。在此覆盖中,仅考虑具有逻辑运算符的表达式。
例如,如果表达式具有布尔运算,如 AND、OR、XOR,则表示总的可能性。
条件覆盖不保证完全的决策覆盖。
计算条件覆盖率的公式
示例
对于上述表达式,我们有 4 种可能的组合
- 真真
- 假假
- 真假
- 假真
考虑以下输入
X=3
Y=4 |
(x真 |
条件覆盖率是 1/4 = 25% |
|
A=3
B=4 |
(a>b) | 假 |
有限状态机覆盖
有限状态机覆盖无疑是最复杂的代码覆盖方法。这是因为它作用于设计的行为。在此覆盖方法中,您需要查找特定状态被访问和转换的次数。它还检查有限状态机中包含的序列数量。
选择哪种类型的代码覆盖率
这无疑是最难回答的问题。为了选择一种覆盖方法,测试人员需要检查:
- 被测代码存在单个或多个未发现的缺陷
- 潜在惩罚的成本
- 声誉损失的成本
- 销售损失的成本等。
缺陷导致代价高昂的生产失败的可能性越高,您需要选择的覆盖级别就越严格。
代码覆盖率与功能覆盖率
代码覆盖率 | 功能覆盖率 |
---|---|
代码覆盖率说明了您的测试平台对源代码的测试程度。 | 功能覆盖率衡量您的测试平台对设计功能的覆盖程度。 |
从不使用设计规范 | 使用设计规范 |
由开发人员完成 | 由测试人员完成 |
代码覆盖率工具
以下是重要的代码覆盖率工具列表:
工具名称 | 描述 |
---|---|
Cobertura | 它是一个开源代码覆盖率工具。它通过检测代码库来衡量测试覆盖率,并分析在测试套件运行时哪些代码行被执行,哪些未被执行。 |
Clover | Clover 还通过只运行覆盖自上次构建以来修改过的应用程序代码的测试来减少测试时间。 |
DevPartner | DevPartner 使开发人员能够分析 Java 代码的代码质量和复杂性。 |
Emma | EMMA 支持类、方法、行和基本块覆盖,以及聚合的源文件、类和方法级别。 |
Kalistick | Kalistick 是一个第三方应用程序,它从不同的角度分析代码。 |
CoView 和 CoAnt | Coding Software 是一款代码覆盖率工具,用于度量、模拟对象创建、代码可测试性、路径和分支覆盖等。 |
C++ 的 Bullseye | BulseyeCoverage 是用于 C++ 和 C 的代码覆盖率工具。 |
Sonar | Sonar 是一款开源的代码覆盖率工具,可帮助您管理代码质量。 |
使用代码覆盖率的优点和缺点
代码覆盖率的优点 | 代码覆盖率的缺点 |
---|---|
有助于评估代码覆盖率的量化度量 | 即使设计中未实现任何特定功能,代码覆盖率仍会报告 100% 的覆盖率。 |
它允许您创建额外的测试用例以增加覆盖率 | 借助代码覆盖率,无法确定我们是否测试了某个功能的所有可能值 |
它允许您找到一组测试用例未执行的程序区域 | 代码覆盖率也不能说明您覆盖了多少逻辑以及覆盖得有多好 |
在未实现指定功能或未包含在规范中的情况下,基于结构的技术无法发现该问题。 |
摘要
- 代码覆盖率是描述程序源代码被测试程度的度量
- 它有助于衡量测试实施的效率
- 五种代码覆盖方法是:1)语句覆盖 2)条件覆盖 3)分支覆盖 4)开关覆盖 5)FSM 覆盖
- 语句覆盖涉及源代码中所有可执行语句至少执行一次
- 决策覆盖报告每个布尔表达式的真或假结果
- 在分支覆盖中,测试代码模块的每个结果
- 条件将揭示条件语句中的变量或子表达式是如何评估的
- 有限状态机覆盖无疑是最复杂的代码覆盖方法
- 为了选择一种覆盖方法,测试人员需要检查潜在惩罚、声誉损失、销售损失等成本。
- 代码覆盖率告诉您测试平台对源代码的测试程度,而功能覆盖率衡量设计功能的覆盖程度
- Cobertura、JTest、Clover、Emma、Kalistick 是几个重要的代码覆盖工具
- 代码覆盖率允许您创建额外的测试用例以增加覆盖率
- 代码覆盖率无助于您确定我们是否测试了某个功能的所有可能值