前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅谈代码覆盖率

浅谈代码覆盖率

作者头像
用户5521279
发布2019-08-16 16:43:27
1.7K0
发布2019-08-16 16:43:27
举报
文章被收录于专栏:搜狗测试搜狗测试

前言

代码覆盖率作为一个指导性指标,可以一定程度上反应测试的完备程度,是软件质量度量的一种手段。100%覆盖的代码并不意味着100%无bug的应用,代码覆盖率作为质量目标没有任何意义,而我们应该把它作为一种发现未被测试覆盖的代码的手段。

代码覆盖率意义

1.了解测试情况

测试过程中覆盖和未覆盖的地方,可能存在的风险。分析未覆盖代码,反推在测试设计是否充分,进一步明确测试设计阶段的问题。

2.发现测试死角、冗余代码、历史废弃代码

有助于发现多个测试用例都覆盖不到的代码,收集方法覆盖率,为废弃的代码提供依据。

3.度量自动化用例

为自动化用例提供覆盖率统计情况,分析覆盖率报告,完善自动化用例。

4.精准回归

构建代码调用关系,精准的确定回归测试范围,避免了全量回归造成测试资源的浪费。

代码覆盖度量方法

1.语句覆盖(StatementCoverage)

又称行覆盖,段覆盖,基本块覆盖,这是最常用也是最常见的一种覆盖方式,就是度量被测代码中每个可执行语句是否被执行到了。语句覆盖常常被人指责为“最弱的覆盖”,它只管覆盖代码中的执行语句,却不考虑各种分支的组合等等。

2.判定覆盖(DecisionCoverage)

又称分支覆盖,所有边界覆盖,基本路径覆盖,判定路径覆盖。它度量程序中每一个判定的分支是否都被测试到了。这句话是需要进一步理解的,应该非常容易和下面说到的条件覆盖混淆。因此我们直接介绍第三种覆盖方式,然后和判定覆盖一起来对比,就明白两者是怎么回事了。

3.条件覆盖(ConditionCoverage)

条件覆盖度量判定中的每个子表达式结果true和false是否被测试到了。

为了说明判定覆盖和条件覆盖的区别,我们来举一个例子,假如我们的被测代码如下:

int foo(int a, int b)

{ if (a < 10 || b < 10) // 判定 { return 0; // 分支一 } else { return 1; // 分支二 } }

设计判定覆盖案例时,我们只需要考虑判定结果为true和false两种情况,因此,我们设计如下的案例就能达到判定覆盖率100%:

TestCaes1: a =5, b = 任意数字 覆盖了分支一 TestCaes2: a =15, b =15 覆盖了分支二

设计条件覆盖案例时,我们需要考虑判定中的每个条件表达式结果,为了覆盖率达到100%,我们设计了如下的案例:

TestCase1: a =5, b =5true, trueTestCase4: a =15, b =15false, false

通过上面的例子,我们应该很清楚了判定覆盖和条件覆盖的区别。需要特别注意的是:条件覆盖不是将判定中的每个条件表达式的结果进行排列组合,而是只要每个条件表达式的结果true和false测试到了就OK了。因此,我们可以这样推论:完全的条件覆盖并不能保证完全的判定覆盖。比如上面的例子,假如我设计的案例为:

TestCase1: a =5, b =15true, false 分支一 TestCase1: a =15, b =5false, true 分支一

我们看到,虽然我们完整的做到了条件覆盖,但是我们却没有做到完整的判定覆盖,我们只覆盖了分支一。

4.路径覆盖(PathCoverage)

又称断言覆盖(PredicateCoverage)。它度量了是否函数的每一个分支都被执行了。这句话也非常好理解,就是所有可能的分支都执行一遍,有多个分支嵌套时,需要对多个分支进行排列组合,可想而知,测试路径随着分支的数量指数级别增加。

Java代码覆盖率原理

主流代码覆盖率工具都采用字节码插桩模式,通过钩子的方式来记录代码执行轨迹信息。其中字节码插桩又分为两种模式On-The-Fly和Offine。On-The-Fly模式优点在于无需修改源代码,可以在系统不停机的情况下,实时收集代码覆盖率信息。Offine模式优点在于系统启动不需要额外开启代理,但是只能在系统停机的情况下才能获取代码覆盖率。

On-The-Fly插桩 Java Agent

JVM中通过-javaagent参数指定特定的jar文件启动Instrumentation的代理程序代理程序在每装载一个class文件前判断是否已经转换修改了该文件,如果没有则需要将探针插入class文件中。代码覆盖率就可以在JVM执行代码的时候实时获取。典型代表:Jacoco

On-The-Fly插桩 Class Loader

自定义classloader实现自己的类装载策略,在类加载之前将探针插入class文件中。典型代表:Emma

Offine插桩

测试之前先对文件进行插桩,生成插过桩的class文件或者jar包,执行插过桩的class文件或者jar包之后,会生成覆盖率信息到文件,最后统一对覆盖率信息进行处理,并生成报告。Offine插桩又分为两种:Replace:修改字节码生成新的class文件Inject:在原有字节码文件上进行修改。典型代表:Cobertura、Jacoco

总结

本文主要介绍了代码覆盖率和Java覆盖率的统计原理。不管是白盒测试还是黑盒测试,代码覆盖率统计都是必不可少的一环,它可以直接反映测试的遗漏点(不是100%反映)。

最后重申下本文开篇观点:

  • 代码覆盖率统计是用来发现没有被测试覆盖的代码
  • 代码覆盖率统计不能完全用来衡量代码质量
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 搜狗测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档