[代码质量标准定义] Sonar规则、覆盖率与QualityGate

本文档要回答以下问题:

  1. 要使用哪些规则进行检查?单元测试覆盖率多少?重复率多少?怎样才算通过?为什么?
  2. 实战中怎么使用?

1 Sonar 检查规则

1.1 规则的分类

按照问题严重级别,分为以下4类:

  • Bug(可靠性)
  • Vulnerability(漏洞)
  • Code Smell(可维护性)
  • Security Hotspot(安全疑点,可能不需要修复,需要人工检查)

1.2 Sonar 常见的可用规则库对比

Sonar 中,可以用插件的方式,把其他静态检查工具的规则加进来。以下是常见规则库的对比。

用色块标出了强关联的规则库。例如,只要安装了 FindBugs 插件,就会得到 3 个规则库,这三个库就是强关联的。

(版本不同,具体数字可能会有差异)

名称 链接 规则数

活跃度

(Github Star)

推荐指数及理由
Bug Vulner-ability Code Smell Security Hotspot 合计
SonarAnalyzer
  • 维护者:SonarSource
  • ref
  • Sonar内置
  • 有IDEA插件,Sonarlint
124 42 341 34 541 594

5星。

  • Sonar 内置
  • 覆盖全面
Common Java 1 0 5 0 6  
Checkstyle
  • ref
  • 主要用于统一代码风格
  • 有 IDEA 插件
1 0 166 0 167 5.1k

4星。

  • 默认支持 Google Java Style Guide 和 Sun Code Conventions
PMD
  • ref
  • PMD 有 IDEA 插件
3 2 263 0 268 2.7k


4星。

  • Code Smell 较多
  • 阿里的 p3c 是基于它实现的
PMD Unit Tests 0 0 17 0 17  
PMD_P3C
  • 维护者:阿里质效团队
  • ref
  • 在PMD基础上,根据《阿里巴巴Java代码规范》编写的规则
  • 有 IDEA 插件
8 19 28 0 55 20.1k

4星。

  • Star 数极高
  • 资料丰富,网上一搜基本都是它
  • 我们的技术栈与阿里较为接近。阿里内部踩过坑,相当于做了一次筛选
  • IDEA 插件比较好用

问题:

  • 书上的规则还有很多没实现,不全
  • 个别规则不合理。例如 JVMHelper,会被判错。
FindBugs
  • ref
  • 用来查找Java代码中的程序错误。原来的 Findbugs已经不更新了,我们实际用的是 Spotbugs
  • 有 IDEA 插件
237 10 202 0 449 1665


5星。

  • bug 和漏洞扫得很多,是比较重要的东西。
  • 成名已久,稳定性好。
  • 近期迭代频次高
FindBugs Contrib
  • ref
  • FindBugs的辅助
224 0 78 0 302  
Find Security Bugs
  • ref
  • 同上,主打安全漏洞
0 116 0 0 116  

1.3 最终选择

第一版方案

(SonarAnalyzer(剔除所有SecurityHotspot) + Common Java) + (FindBugs + Find Security Bugs)

理由:覆盖全面,文档齐全,使用方便。经本地测试验证,FindBugs Contrib 很多bug规则没必要,或者已经被 Sonar 涵盖。

后续提升方案

在所有规则中筛选,挑出适合我们的规则集合。

IDEA 侧,自己开发一个插件,确保规则一致。

2 单元测试代码覆盖率标准

2.1 优秀 Java 开源项目的指标

项目
行覆盖率
代码量(java行数/总数)
数据来源
Apache Dubbo 64% 157k / 172k 本地 jacoco 扫描,再用 IDEA 汇总数据
Jacoco 95% 37k / 52k

https://www.jacoco.org/jacoco/trunk/coverage/

Junit4 86% 31k / 37k 本地 jacoco 扫描
SonarQube 89.9% 197k / 292k https://sonarcloud.io/dashboard?id=org.sonarsource.sonarqube%3Asonarqube
p3c-pmd 85% 4k / 12k 本地 idea 扫描

2.2 大厂覆盖率调研

公司
覆盖率要求
来源
阿里

语句覆盖率达到70%;核心模块的语句覆盖率和分支覆盖率都要达到100%。

某些部门不要求。

阿里巴巴Java开发手册

采访1人

SAP 成熟项目80%;新建初始项目50%。要求明年到 85%。没有固定值,每年要提高,不留技术债。 采访1人
华为 一般是 75%、85%。某些部门不要求。 采访2人
爱彼迎 核心 100%,产品功能 80% 采访1人
腾讯 某些部门不要求,说是业务太多没时间写 采访2人
拼多多 某些部门不要求 采访1人

从调研结果可以看出:

  1. 国内高速发展的互联网公司中,相当大一部分是不要求单元测试覆盖率的。原因是,业务太多,变化太快,产品不成熟。
  2. 华为、腾讯、阿里中,部门之间存在较大差异。拥有成熟产品的部门,应该是严格要求单元测试的(这里是推测,微信、淘宝这种产品,很难想象没有单元测试)。
  3. 成熟的外企,如 SAP、爱彼迎,对单元测试覆盖率的要求都比较高。

2.3 标准确定

新增代码的覆盖率 70%。一段时间之后(如半年到1年),逐步增加至 75% ~ 85%。

理由:

可以看出这样一个规律:产品成熟度越高,对单元测试覆盖率的要求也越高。(当一个产品能产生足够大和稳定的现金流之后,可以花更多的精力来打磨质量)

根据我们目前的情况,目标太激进难以上手,太低了没有意义,不妨遵循《阿里巴巴Java开发手册》的建议。

3 Sonar 的 QualityGate

覆盖率改为 70%,安全性评分改为 B,其他与 Sonar 内置的方案一致。

标准详解:

  • 覆盖率大于等于 70%。这里的覆盖率是由行覆盖率和分支覆盖率计算出来的;
  • 重复代码小于等于 3.0%;
  • 技术债评分为 A,即各种 CodeSmell 加在一起的负债时间低于本次开发时间的 5%;
  • 可靠性评分为 A,0 bug;
  • 安全性评分为 B,没有重要漏洞。

具体定义可以查阅文档:https://docs.sonarqube.org/latest/user-guide/metric-definitions/