1、代码覆盖率基础知识

测试覆盖率常被用来衡量测试的充分性和完整性,也是测试有效性的一个度量。敏捷开发的大潮之下,如何在快速迭代的同时保证对被测代码的覆盖度和产品质量,是一个非常有挑战性的话题

1.1 代码覆盖率是什么?

代码覆盖率测试技术是一种常见的白盒测试技术,是衡量软件测试工作充分性和完整性的重要指标之一。代码覆盖率指在测试的时候已经被测试过了的代码占准备被测试总代码量的比例和程度,它关注的是在执行测试用例时,有哪些代码被执行到了,有哪些代码没有被执行到

1.2 代码覆盖率的指标

行覆盖率

又称为语句覆盖率,指已经被执行到的语句占总的可执行语句(不包含类似 C++ 的头文件声明、代码注释、空行等等)的百分比。这是最常用也是要求最低的覆盖率指标。
实际项目中通常会结合判定覆盖率或者条件覆盖率一起使用

判定覆盖率

又称分支覆盖率,用以度量程序中每一个判定的分支是否都被测试到了,即代码中每个判断的取真分支和取假分支是否各被覆盖至少一次。
比如,对于 if(a>0 && b>0),就要求覆盖“a>0 && b>0”为 TURE 和 FALSE 各一次

条件覆盖率

判定中的每个条件的可能取值至少满足一次,度量判定中的每个条件的结果 TRUE 和 FALSE 是否都被测试到了。
比如,对于 if(a>0 && b>0),就要求“a>0”取 TRUE 和 FALSE 各一次,同时要求“b>0”取 TRUE 和 FALSE 各一次
另外还有路径覆盖率、函数覆盖率、类覆盖率、圈复杂度

1.3 代码覆盖率的意义

  • 代码覆盖率最主要的意义是帮助我们了解测试情况,即直观了解测试过程中覆盖和未覆盖率的代码,可能存在的风险,然后根据分析未覆盖率代码,反推测试设计是否充分,进一步明确测试设计阶段问题;
  • 其次,代码覆盖率有助于发现多个测试用例都覆盖不到的代码,收集方法覆盖率,为废弃代码提供依据;
  • 此外,代码覆盖率可以度量单元/自动化测试用例,提供覆盖率统计情况,分析覆盖率报告,完善用例;
  • 最后,代码覆盖率利于精准回归,通过构建代码调用关系,精准的确定回归测试范围,避免了全量回归造成测试资源的浪费。

    1.4 代码覆盖率的局限性

    高的代码覆盖率不一定能保证软件的质量。举一个极端的例子,如果一个被测函数里面只有一行代码,只要这个函数被调用过了,那么衡量这一行代码质量的所有覆盖率指标都会是 100%,但是这个函数是否真正实现了应该需要实现的功能呢?显然不是的,我们希望代码覆盖率越高越好,但是,高的代码覆盖率并不一定能保证软件的质量,而低的代码覆盖率一定不能保障软件的质量。因为,代码覆盖率是基于现有代码,无法发现那些未考虑某些输入以及未处理某些情况形成的缺陷。
    此外,在追求更高的代码覆盖率时,会发现测试成本会随着代码覆盖率的提高以指数级的方式迅速增加,花费的时间成本会更高。因为和自动化测试类似,后期需要大量的桩代码,MOCK 代码等方式来控制执行路径

    2、代码覆盖率的常用工具

    代码覆盖率是比较成熟的测试方式,常见的语言均有开源优秀的代码覆盖率工具:

  • Java: JaCoCo、Emma、 Cobertura

  • PHP: Php-code-coverage
  • Python: Coverage.py
  • Javascript: istanbul 、Blanket.js
  • C/C++: gcov、lcov、gcovr
  • Golang: gotest

    3、代码覆盖率的应用场景

    3.1 单元测试

    实际中一般会对底层和核心代码进行单元测试,单元测试聚焦于系统的某一部分,通常是较低级别,是一种以较小代价换取软件“正确”的方法。单元测试框架如 Junit 、TestNG、PhpUnit 等。通过引入代码覆盖率技术,可以衡量和改进单元测试

  • 衡量单元测试用例集合的充分性和完备性

  • 分析覆盖率报告完善测试用例提升覆盖率
  • 与流水线集成,作为准入参考(如代码提交自动触发单元测试,并自动统计代码覆盖率,以单元测试通过率和代码覆盖率为标准决定代码是否提交到仓库,或是否提测上线等)

    3.2 自动化测试

    自动化框架一般都有对应覆盖率的插件支持,自动化测试覆盖率一般分为业务用例覆盖率及代码覆盖率两种。同样的,代码覆盖率技术也有助于衡量和改进自动化测试

  • 衡量自动化测试用例集合的充分性和完备性

  • 分析覆盖率报告完善测试用例提升覆盖率
  • 通过报告细节快速定位并修复缺陷
  • 与流水线集成

    3.3 手工测试

    如应用到日常项目测试,服务端的版本迭代或客户端的版本迭代
    手工测试中,一般更要关注 增量覆盖率,即首要关注本次变动的代码覆盖率情况

    3.4 代码覆盖率平台

    随着覆盖率在各个阶段的应用,对于整个测试周期(单元测试、接口测试、UI测试、集成测试)等,如何量化测试完整度和有效性?此外,不同编程语言有不同的工具环境要求,如何支持多语言的代码覆盖率收集、管理呢。这种背景下,就会驱动覆盖率平台的需求建设。一般来说,代码覆盖率平台需求应当 具备以下功能点:

  • 支持多种开发语言的覆盖率测试(如PHP、JAVA、PYTHON等)

  • 支持不同类型的覆盖率测试(如单元测试、自动化测试、功能测试等)
  • 支持增量覆盖率统计
  • 支持报告持久化,历史覆盖率可以追溯
  • 支持平台化操作,简单便捷
  • 支持一键接入,解决手工配置繁琐问题

    3.4 基于代码覆盖率的精准测试

    前面提到代码覆盖率利于精准回归,通过构建代码调用关系,精准的确定回归测试范围,避免了全量回归造成测试资源的浪费。那么什么是精准测试?
    精准测试是借助一些高效的算法和工具,收集、可视化并且分析原生测试数据,建立起一套测试系统,它是对传统测试的补充,采用的是黑盒测试与白盒测试相结合的模式。精准测试的核心思想是建立测试用例和产品代码的双向追溯,如图所示:
    图片1.jpg
    正向追溯:可以追溯case执行路径,为排查、定位问题快速提供依据
    反向追溯:通过代码变更快速圈定相关的case集合,降低回归的盲目性和工作量
    精准测试是建立在代码覆盖率之上的,因为双向追溯采用了代码覆盖率统计技术,双向追溯将覆盖率分析和计算精准到测试用例针对的产品代码上

    4、总结

    代码覆盖率是一种常见的白盒测试技术,有极高的应用价值,利于衡量评估软件测试工作的充分性和完整性。在实际工作场景中,借助于优秀的代码覆盖率工具技术可以将代码覆盖率应用到单元测试、自动化测试、功能集成等环节中,提高项目交付质量效率。但是,代码覆盖率也有局限性,高的代码覆盖率并不一定保证软件质量,一味追求高的覆盖率还会大幅增加开发测试成本。因此,正确恰当地应用代码覆盖率非常关键。