前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Lombok有毒慎用?会导致覆盖率崩塌?

Lombok有毒慎用?会导致覆盖率崩塌?

作者头像
Antony
发布2021-03-10 14:50:33
5.5K0
发布2021-03-10 14:50:33
举报
文章被收录于专栏:软件测试那些事

有没有发现,在引入Lombok之后,jacoco扫出来的覆盖率是不是一下子掉下来了?

Lombok 由于其使用的便利性, 目前流传非常广泛。甚至有呼声希望其能被Java官方引入,成为JDK的一部分。

当然凡事都有两面性,Lombok的引入也是有代价的。一时注释一时爽,结果导致代码在不知不觉中翻了好几倍。

例如以下几个简单的注解,背后是N多个自动生成的方法,

  • @Data注解:这是若干个注解的组合,包括有@Setter、@Getter、@ToString和@EqualsAndHashCode的功能,还会添加一个公共的构造方法。staticConstructor 参数可将构造方法置为private,并提供一个获取对象的静态方法。
  • @Builder:使用私有构造函数生成一个名为TBuilder的内部类,创建一个构造器。
  • @NoArgsConstructor:该注解使用在类上,该注解提供一个无参构造
  • @AllArgsConstructor:该注解使用在类上,该注解提供一个全参数的构造方法,默认不提供无参构造方法。

这其中尤其是@Data这个注解,会附带相当多的方法。

默认情况下,由于Jacoco不会区分Lombok生成的代码和正常的源代码。结果,在引入Lombok后就会发现,覆盖率通常会低得让人匪夷所思。例如某个项目,通过Jacoco获取到的代码行数以及覆盖率为:

可见,这个覆盖率是非常低的,会被质量门禁判违规(常见会要求>50%甚至>80%)。

这种情况下,开发者一般会有两个选择:

  1. 专门为这些生成的代码编写单元测试用例
  2. 要求降低质量门禁中的覆盖率要求

通常这两个方案都是不可取的。

专门为这些生成的代码编写用例是没有意义的。既然使用了Lombok,一个默认的前提就是Lombok是正确可靠的,为这些自动生成的代码进行单元测试不是一件高优先级的事情,还是放过已经996的码农和他们的头发吧,要爱护那些愿意写单元测试的好同志。

第二种方案也不可取,这会引入一个非常不好的开始,因为破窗效应,马上质量门禁也没有意义了。千万个教训告诉我们,千万不要去考验人性。

两种选择都没有意义,也都不可取,于是马上就有人想到了第三种方法

3 手工排除Bean

无论是Jacoco还是Sonar,都提供了exclude的方式,通过配置项来指定统计时排除某些特定的包或者类。如对于Jacoco可以在jacoco-maven-plugin的<configuration>中有如下配置,用于排除指定的内容。

代码语言:javascript
复制
<configuration>
<excludes>
<exclude>**/*DTO.*</exclude>
<exclude>**/domain/**/*</exclude>
</excludes>
</configuration>

第一个<exclude>标签将吧所有DTO结尾的类排除,而第二个<exclude>标签将把domain目录和子目录下的所有类都排除出去。

通过这个方式,也可以在数据源头上进行排除。

类似的,还可以通过基于jacoco覆盖率报告来自研解析工具,进行覆盖率或者增量覆盖率计算。这个过程中,也可以指定需要排除的包或者类,实现类似的做法。

当然,这种方式也需要项目有一些项目结构和命名上的约定,以保证过滤的正确。另外,既然放开了过滤的条件,有可能会让人钻空子。

4 使用Sonarqube 而不是Jacoco的结果

虽然Jacoco中的数据受到了lombok的污染,但是SonarQube由于有自身代码行的计算是根据扫描的源码,再根据自身的算法进行计算,并不是根据Jacoco提供的数据。再由此计算覆盖率的时候,就可以部分规避掉这个问题了。所以这是一个正解。当然,由于SonarQube和Jacoco的代码行、覆盖率等算法有差异,最好是保持指标数据源前后的一致性,避免混用。

5 使用lombok.addLombokGeneratedAnnotation

其实从Jacoco 0.8.0开始,其实就具备了可以将lobmok生成的代码从Jacoco报告中排除的能力。发布说明可以参见

https://github.com/jacoco/jacoco/pull/513

具体做法是,在项目的根目录下新建一个名字为lombok.config的文件,里面有如下的内容,

代码语言:javascript
复制
config.stopBubbling = true
lombok.addLombokGeneratedAnnotation = true

Lombok在为由其生成的构造方法、方法、字段和类型中增加@Generated注解,然后Jacoco借助这个注解来实现更为准去的排除。排除以后的结果如下,

当然,这个方案对两者的版本也有限制,要求Lombok >= 1.16.14, jacoco>0.8.0

本文案例图片来自: rainerhahnekamp ,案例源码可以从 GitHub 上获取。

总结一下,面对lombok,有如下五种解决方案,推荐后两种哦。

1专门为这些生成的代码编写单元测试用例 【X】

2要求降低质量门禁中的覆盖率要求【X】

3手工排除Bean 【X】

4使用Sonarqube 而不是Jacoco的结果【OK】

5使用lombok.addLombokGeneratedAnnotation 【OK】

覆盖率统计,我们是认真的

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 软件测试那些事 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 有没有发现,在引入Lombok之后,jacoco扫出来的覆盖率是不是一下子掉下来了?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档