都100%代码覆盖了,还会有什么问题?_最新动态_新闻资讯_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 新闻资讯 > 最新动态 > 都100%代码覆盖了,还会有什么问题?

都100%代码覆盖了,还会有什么问题?

 2017/10/1 16:43:07    程序员俱乐部  我要评论(0)
  • 摘要:文|齐磊ThoughtWorks资深质量保证咨询师,超过7年的软件开发与测试经验,擅长测试开发,软件开发流程的自动化,目前致力于开阔移动端测试开发领域。引言(图片来自:http://t.cn/R06rQHi)很多人看到这个标题时,都会想“你都100%代码覆盖了,怎么还会有问题呢?”让我们看一下代码例子:publicclassTestCalculator{publicDoubleadd(Doublea,Doubleb){returna+b;}
  • 标签:问题 代码 什么

  文|齐磊

  ThoughtWorks 资深质量保证咨询师,超过 7 年的软件开发与测试经验,擅长测试开发,软件开发流程的自动化,目前致力于开阔移动端测试开发领域。

  引言

(图片来自:http://t.cn/R06rQHi)

  很多人看到这个标题时,都会想“你都 100% 代码覆盖了,怎么还会有问题呢?” 让我们看一下代码例子:

public class TestCalculator {
       public Double add (Double a, Double b) {
              return a + b;}
}

  再看看用 junit 写出的测试代码:

@Test
public void testAdd () {
       Double a = new Double (1);
       Double b = new Double (2);
       Double c = new Double (3);
       assertEquals (c, testCalculator.add (a, b));
}

  当我们使用 EclEmma 或者 Jacoco 来进行覆盖测试时,对于这个类,我们将得到 100% 测试覆盖率

  一切看起来都那么的完美,真是这样的吗?

  好吧,让我们来来看看另一个测试,当其中一个变量为 null 时,返回值将会是什么?

@Test
public void testAddNullPointerException () {
       Double a = new Double (1);
       Double b = null;
       Double c = new Double (3);
       assertEquals (c, testCalculator.add (a, b));
}

  好了,你会发现尽管覆盖率为 100%,但程序却抛出了 NullPointerException。

  那么肯定有人会问,这样的话单元测试覆盖率的高低都不能作为衡量项目代码质量的指标,那么我们要单元测试还有什么用?

  首先,我想我们可能搞错了测试覆盖的定义。

  我们先听听 Martin Fowler 对于测试覆盖的定义:

  Test coverage is a useful tool for finding untested parts of a codebase. Test coverage is of little use as a numeric statement of how good your tests are.

(图片来自:https://martinfowler.com/bliki/TestCoverage.html)

  他认为:把测试覆盖作为质量目标没有任何意义,我们应该把它作为一种发现未被测试覆盖的代码的手段。

  所以 100% 的代码覆盖率还值得追求吗?

  当然,这应该是每个程序员毕生的追求之一,但是如果从项目角度考虑 ROI (投入产出比),对于需要快速上线的短期项目,需要注重的是让测试覆盖核心功能代码。如果你的项目是一个长期项目,那么高覆盖率是非常有必要的,它意味着高可维护性,以及更少的 bug。(前提是你的测试采用 TDD/BDD 方式编写,我见过将测试代码写的一团糟的人,看着他的代码,我宁愿重新写一遍)

  那么对于一个项目来说,覆盖率应该达到多少?

  其实没有适用于所有项目的数值,每个项目都应有自己的阈值,但共性是,测试必须覆盖主要业务场景,代码的逻辑分支也必须尽可能的覆盖。

  如何改进你的项目代码覆盖率?

  首先我们要阅读和理解项目代码,找出其中需要测试并且与业务强相关的代码,结合 sonar 等代码质量管理平台,从代码编写规范、复杂度、重复代码等方面进行代码重构,进一步提高项目的可维护性与可读性。

  这也意味着重构,重构的同时,你需要更多的测试来保证你重构代码的正确性。

  其次要对 code coverage 进行度量分析,那么我们应该怎么度量 code coverage?

  一般来说我们从以下四个维度来度量,如上图所示:

  1. 行覆盖率(line coverage):度量被测代码中每个可执行语句是否都被执行到,但不包括 java import,空行,注释等。
  2. 函数覆盖率function coverage):度量被测代码中每个定义的函数是否都被调用。
  3. 分支覆盖率(branch coverage):度量被测代码中每一个判定的分支是否都被测试到。
  4. 语句覆盖率(statement coverage):度量被测代码是否每个语句都被执行。

  所以行覆盖率的高低不能说明项目的好坏,我们要从多方面进行思考,一般我们遵循的标准应是:函数覆盖率 > 分支覆盖率 > 语句覆盖率**

  代码覆盖率最重要的意义在于:

  • 阅读分析之前项目中未覆盖部分的代码,进而反推在前期 QA 以及相关测试人员在进行黑盒测试设计时是否考虑充分,没有覆盖到的代码是否是测试设计的盲点,为什么没有考虑到?是需求或者 UX 设计不够清晰,还是测试设计的理解有误。
  • 检测出程序中的废代码,可以逆向反推代码设计中不合理的地方,提醒设计/开发人员理清代码逻辑关系,提升代码质量。
  • 代码覆盖率高不能说明代码质量高,但是反过来看,代码覆盖率低,代码质量绝对不会高到哪里去,可以作为测试自我审视的重要工具之一。

  结束语

  单元测试的覆盖率并不只是为了取悦客户或者管理层的数据,它能够实实在在反应项目中代码的健康程度,帮助我们更好的改善了代码的质量,增加了我们对所编写代码的信心。


  更多精彩洞见,请关注微信公众号:思特沃克

发表评论
用户名: 匿名