玩转一下 SonarQube 代码质量管理平台

发布于 2022-09-22 22:56:33 字数 28267 浏览 6 评论 0

SonarQube 社区版是开源的代码质量管理平台,涵盖了架构设计、注释、编码规范、潜在缺陷、代码复杂度、单元测试、重复代码7个维度。通过强大的插件扩展机制,支持对主流编程语言的指标分析,目前可以支持超过20种以上主流编程语言。

SonarQube 在进行代码质量管理时,会从下图所示的七个纬度来分析项目的质量。

SonarQube 在进行代码质量管理时,会从七个纬度来分析项目的质量。

  • 糟糕的复杂度分析:文件、类、方法等,如果复杂度过高将难以改变,这会使得开发人员难以理解它们,且如果没有自动化的单元测试,对于程序中的任何组件的改变都将可能导致需要全面的回归测试。

  • 重复:显然程序中包含大量复制粘贴的代码是质量低下的,sonar可以展示源码中重复严重的地方。

  • 缺乏单元测试:可以很方便的统计并展示单元测试覆盖率。

  • 没有代码标准:sonar 可以通过 PMD、CheckStyle、Findbugs 等等代码规则检测工具规范代码编写.

  • 没有足够的或者过多的注释:没有注释将使代码可读性变差,特别是当不可避免地出现人员变动时,程序的可读性将大幅下降,而过多的注释又会使得开发人员将精力过多地花费在阅读注释上,亦违背初衷。

  • 潜在的 bug:可以通过 PMD、CheckStyle、Findbugs 等等代码规则检测工具检测出潜在的缺陷。

    issue 的类型分为五个:

    • [Blocker]阻断:错误,高概率影响程序运行,例如:内存泄漏,未关闭的JDBC连接等等,代码必须修复。
    • [Critical]严重:低概率影响程序运行活着一个安全漏洞的错误,例如:空catch块,SQL注入等,这样的代码需要立即审查。
    • [Major]主要:代码缺陷,影响开发人员的生产力,例如:裸露一段代码,复制代码块,未使用的参数,这样的代码需要关注或忽略。
    • [Minor]次要:可能较少的影响开发人员生产力,这样的代码需要关注或忽略。。
    • [info]信息:不是错误,也不是质量缺陷,只是发现而已,这样的代码可以忽略。
  • 糟糕的设计:可以找出循环,展示包与包,类与类之间的相互依赖关系,可以检测自定义的架构规则。可以管理第三方的jar包,可以利用LCOM4检测单个任务规则的应用情况,检测耦合。

SonarQube 可以测量的关键指标,包括代码错误、 代码异味(code smells)、安全漏洞和重复的代码。

  • 代码错误 是代码中的一部分不正确或无法正常运行、可能会导致错误的结果,是指那些在代码发布到生产环境之前应该被修复的明显的错误。
  • 代码异味 不同于代码错误,被检测到的代码是可能能正确执行并符合预期。然而,它不容易被修复,也不能被单元测试覆盖,却可能会导致一些未知的错误,或是一些其它的问题。从长期的可维护性来讲,立即修复代码异味是明智之举。通常在编写代码的时候,代码异味并不容易被发现,而 SonarQube 的静态分析是一种发现它们的很好的方式。
  • 安全漏洞 正如听起来的一样:指的是现在的代码中可能存在的安全问题的缺陷。这些缺陷应该立即修复来防止黑客利用它们。
  • 重复的代码 也和听起来的一样:指的是源代码中重复的部分。代码重复在软件设计中是一种很不好的做法。总的来说,如果对一部分代码进行更改而另一部分没有,则会导致一些维护性的问题。例如,识别重复的代码可以很容易的将重复的代码打包成一个库来重复的使用。
  • 为什么它那么重要

SonarQube 为组织提供了一个集中的位置来管理和跟踪多个项目代码中的问题。它还可以把持续的检查与质量门限相结合。一旦项目分析过一次以后,更进一步的分析会参考软件最新的修改来更新原始的统计信息,以反映最新的变化。这些跟踪可以让用户看到问题解决的程度和速度。这与 “尽早发布并经常发布”不谋而合。

另外,SonarQube 可使用 可持续集成流程,比如像 Hudson 和 Jenkins 这样的工具。这个质量门限可以很好的反映代码的整体运行状况,并且通过 Jenkins 等集成工具,在发布代码到生产环境时担任一个重要的角色。

本着 DevOps 的精神, SonarQube 可以量化代码质量,来达到组织内部的要求。为了加快代码生产和发布的周期,组织必须意识到它们自己的技术债务和软件问题。通过发现这些信息, SonarQube 可以帮助组织更快的生成高质量的软件。

组件组成

  • sonarqube server : 他有三个程序分别是 webserver(配置和管理sonar) searchserver(搜索结果返回给sonarUI) ComplateEngineserver(计算服务 将分析结果入库)。
  • sonarqube db : 数据库 存放配置。
  • sonarqube plugins: 插件增加功能。
  • sonar-scanner : 代码扫描工具 可以有多个。

SonarQube 各组件的工作流程

  1. 开发者在IDE中编码,并使用SonarLint执行本地代码分析;
  2. 开发者向软件配置管理平台(Git,SVN,TFVC等)提交代码;
  3. 代码提交触发持续集成平台自动构建、使用SonarQube Scanner执行分析;
  4. 分析报告被发送到SonarQube Server进行处理;
  5. 处理好的报告生成对应可视化的视图,并将数据保持到数据库;
  6. 开发者可以在页面通过查看,评论,解决问题来管理和减少技术债;

SonarQube 中的一些重要概念

指标:SonarQube 中的主要指标有可靠性,安全性,可维护性,测试覆盖率,复杂度,重复代码,规模(大小),问题等。

  • 代码规则:在 SonarQube 中,通过插件提供的规则,在执行代码分析时对代码进行分析并生成问题。由于规则中定义了修复问题话费的成本(时间),解决问题的代价以及技术债可以通过这些问题进行计算。规则一般有三种类型:可靠性(Bug),可维护性(坏味道),安全性(漏洞)。
  • 质量配置:质量配置提供了根据需求配置一组代码规则的能力,这组代码规则将被用于分析某些指定的组件(项目)。例如,项目A对应什么编程语言,适用于那些代码规则等等。
  • 质量阈:质量阈是一系列对项目指标进行度量的条件。项目必须达到所有条件才能算整体上通过了质量阈。例如,配置质量阈为新增Bugs大于10,新代码可靠率低于评级A,新代码可维护率低于评级B,那分析完成后若指标符合这些标准,则代码质量将被认为是不合格的。

SonarQube Server 处理分析报告时,根据质量配置中的代码规则进行匹配,从而生成具体的指标数据,然后根据质量阈中的阈值判断出项目的代码是否合格。

下载社区版

maven 配置

详见:https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner+for+Maven

<settings>
    <pluginGroups>
        <pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
    </pluginGroups>
    <profiles>
        <profile>
            <id>sonar</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <!-- Optional URL to server. Default value is http://localhost:9000 -->
                <sonar.host.url>
                  http://localhost:9000
                </sonar.host.url>
            </properties>
        </profile>
     </profiles>
</settings>

在项目 pom.xml 中添加 maven 插件,以及排除文件

 <properties>
    <sonar.exclusions>**/persistence/generated/*.java</sonar.exclusions>
  </properties>

  <build>
    <plugins>
        <plugin>
          <groupId>org.sonarsource.scanner.maven</groupId>
          <artifactId>sonar-maven-plugin</artifactId>
          <version>3.6.0.1398</version>
        </plugin>
    </plugins>
  </build>

运行 mvn clean verify sonar:sonar,或者不修改项目 pom 配置,直接运行 mvn clean verify org.sonarsource.scanner.maven:sonar-maven-plugin:3.6.0.1398:sonar

Sonar 项目主要指标以及代码坏味道详解

原文 | 官方文档

Reliability 可靠性

Reliability Rating

可靠性比率的计算方法

  • A = 0 Bug 最高等级A,表示代码无bug
  • B = at least 1 Minor Bug 代码只要有一个次要bug,等级就为B
  • C = at least 1 Major Bug 只要包含一个重要bug,等级将为C
  • D = at least 1 Critical Bug 只要有一个严重bug,等级评估为D
  • E = at least 1 Blocker Bug 只要有一个最高等级的阻断级别的bug,可靠性评估为E,最低级别。

Reliability remediation effort 修复所有缺陷问题成本/耗时

Reliability remediation effort on new code 在新增代码上修复所有缺陷问题成本/耗时

备注

图中气泡大小根据 bug 数变化,bug 数越大气泡越大。视觉更加直观。

Security 安全性

Security Rating

安全度指标计算方法

  • A = 0 Vulnerability 没有漏洞时,项目评估为最高级别A
  • B = at least 1 Minor Vulnerability 只要包含一个次要漏洞,项目评估为级别B
  • C = at least 1 Major Vulnerability 只要包含一个重要漏洞,项目评估为级别C
  • D = at least 1 Critical Vulnerability 只要包含一个严重漏洞,评估为D
  • E = at least 1 Blocker Vulnerability 只要包含一个阻断漏洞,项目评估为最低级别E

备注

lines of code 计量方法:包括至少一个字符,不包括空格。

图中气泡大小根据漏洞数变化,漏洞数越大气泡越大。视觉上直观显示。

Maintainability 可维护性

Technical Debt

技术债务 概念,这个概念最早是在 1992 年由 Ward Cunningham 在他的论文 The WyCash Portfolio Management System 中提出的,之后被软件工程界接受并推广,《重构》的作者 Martin Fowler 也在其网站上对技术债务有所介绍。其实原理可以理解为“出来混早晚要还的”,当前不规范的代码,会对以后产品修改的成本造成影响。Technical Debt 计算公式如下:

开发成本

开发一行代码(LOC)的成本。 示例:如果开发1 LOC 的成本估计为30分钟,则此属性的值为 30。目前我们采用的是系统默认值30。注意此处成本是指从零开始重写代码所需的成本。

可维护性

可维护性等级范围从 A(非常好)到 E(非常差)。 评级由技术债务比率的值决定,技术债务比率是将项目的技术债务与从零开始重写代码所需的成本进行比较。 A到D的默认值为0.05,0.1,0.2,0.5。任何超过0.5评级就为E。

举个例子:假设开发成本是30分钟,2,500 LOC 的技术债务为 24,000 分钟的项目将有技术债务比率为 24000 /(30 * 2,500)= 0.32。 因此项目的可维护性评级就是 D。

Coverage 覆盖率

Coverage

行覆盖和条件覆盖的混合。单元测试覆盖多少源代码。Coverage = (CT + CF + LC)/(2*B + EL),其中 :

  • CT = conditions that have been evaluated to ‘true’ at least once至少有一次被判断为true的条件数
  • CF = conditions that have been evaluated to ‘false’ at least once 至少一次被判断为false的条件数
  • LC = covered lines = lines_to_cover uncovered_lines 已覆盖的行数
  • B = total number of conditions 条件总数
  • EL = total number of executable lines (lines_to_cover) 所有可执行的代码总行数

Line coverage

单元测试覆盖行数密度:Line coverage = LC / EL

  • LC = covered lines (lines_to_cover - uncovered_lines) 已覆盖的行数
  • EL = total number of executable lines (lines_to_cover) 所有可执行的代码总行数

Condition coverage

Condition Coverage=(CT+CF)/(2*B)

  • CT = 至少一次使用 ‘true’的条件数
  • CF = 至少一次使用 ‘false’ 的条件数
  • B = 条件总数

Unit test success density (%)

测试成功密度=(单元测试总数-(单元测试错误数+单元测试失败数))/单元测试数*100

Duplications 重复

Duplication

SonarQube 使用自己的复制/粘贴检测引擎,可以检测重复:

  1. 在源文件中
  2. 跨项目中的多个文件
  3. 项目的各个模块
  4. 跨多个项目

Duplicated Lines (%)

重复率=重复行数/总行数*100

  • Duplicated blocks:重复代码块行数
  • Duplicated files:重复文件数
  • Duplicated lines:重复行数

处理 Duplicated

  • 分析这些重复,并通过使用继承或其他合适的模式来消除它们(只有在要对块进行单元测试时才这样做)
  • 将复制的更改复制到复制的块上
  • 使用问题和技术债务机制,通过编辑质量配置文件以包括来自公共Sonar存储库的复制块规则,监控成本并跟踪此错误的修复。

Size 大小

Complexity 复杂度

Complexity 复杂度

以下关键词增加复杂性:if, for, while, case, catch, throw, return (不是方法的最后一个语句), &&, ||, ?

备注

else, default, finally不增加复杂度

代码复杂度过高将难以理解、难以维护。

Code Smells 坏味道

某些东西会混淆维护者或在读代码时产生误导。有时,Bug 和 Code Smell 之间的界线是模糊的。 当有疑问时,问自己:打破这条规则的代码是否是程序员想要的? 如果答案是 可能不是,那么它是一个 Bug。 否则它就是一个代码坏味道。

Issues 问题

Open Issues

当前存在的全部问题

Reopened Issues

关闭后又重新打开的问题,可能由于之前误判关闭或者重新出现同样问题,需要再次将问题置为打开状态。

Confirmed Issues

确认的问题 - 通过确认问题,你基本上是承认:“是的,这是一个问题。” ,并将问题从“打开”状态移动到“已确认”状态。

False Positive Issues

误判问题-在上下文中查看问题,你意识到可能由于一些原因判定了这个问题,然而这个问题实际上不是一个问题,因此可以在此处标记为False Positive,然后继续下一步。注意:做此判断的人需要拥有项目的管理员权限。

Won't Fix

不修复的问题 – 通过查看上下文中的关联,你意识到虽然这是一个有效的问题,实际上并不需要修复。因此可以在此处标记为Won't Fix,然后继续下一步。注意做如此判断的人则需要拥有项目的管理员权限。

此 CI 非彼 CI

docker 安装

  1. docker pull sonarqube
  2. docker run -d --name sonarqube -p 9000:9000 -p 9092:9092 sonarqube
  3. http://myserver:9000

使用

  1. 编辑 maven 的 settings.xml
  2. 分析项目 mvn sonar:sonar

不明觉厉的代码质量说的到底是什么?

  • 正确?严格符合规格说明书
  • 相对灵活?
  • 相对简单?
  • 使用公开的算法?
  • 使用了合适的语法?
  • 没有重新发明轮子?
  • 没有代码坏味?
  • 代码紧凑?
  • 代码逻辑清晰明了?
  • 有良好的注释?
  • 有良好的性能?
  • 优雅?不晦涩?

按你胃,谁还有更好的定义?

码农的7个死穴-SonarQube 涵盖代码质量的7个维度

使用 MySQL 数据库

使用嵌入式 H2 数据库的话,SonarQube 会在下方一直显示一条警告信息:

有点碍眼,还是考虑切换到 MySQL 上吧。

Create a new MySQL Schema called sonar

# Create SonarQube database and user.
# Command: mysql -u root -p < create_database.sql
CREATE DATABASE sonar CHARACTER SET utf8mb4 COLLATE utf8_general_ci;

CREATE USER 'sonar' IDENTIFIED BY 'sonar';
GRANT ALL ON sonar.* TO 'sonar'@'%' IDENTIFIED BY 'sonar';
GRANT ALL ON sonar.* TO 'sonar'@'localhost' IDENTIFIED BY 'sonar';
FLUSH PRIVILEGES;

Edit the properties sonar.jdbc.username, sonar.jdbc.password and sonar.jdbc.url in [sonar_qube_root_folder]/conf/sonar.properties file with the next values

sonar.jdbc.username=sonar
sonar.jdbc.password=sonar
sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance

Launch SonarQube (it applies for windows-x86–32)

  1. Go to [sonar_qube_root_folder]/bin/[architecture]/StartSonar.bat
  2. Go to http://localhost:9000/

参考

安装中文包插件

在线安装

Administration->Marketplace->Plugins,搜索 chinese pack,安装之

离线安装

  1. 下载这里
  2. 将插件包复制到 sonarqube/extensions/plugins/ 目录
  3. 重新启动即可

装完后就这样子了

mvn clean verify -DskipTests org.sonarsource.scanner.maven:sonar-maven-plugin:3.6.0.1398:sonar \
  -Dsonar.projectKey=cn.org.bjca.site:bjca-site \
  -Dsonar.host.url=http://192.168.116.82:9000 \
  -Dsonar.login=55fd8d17a90e78365675f70c7c4375075a6fecdd

https://github.com/gabrie-allaigre/sonar-gitlab-plugin 4.0 for 7+

命令行中指定排除目录

mvn clean verify -DskipTests org.sonarsource.scanner.maven:sonar-maven-plugin:3.6.0.1398:sonar \
  -Dsonar.projectKey=usercenter \
  -Dsonar.host.url=http://192.168.116.82:9000 \
  -Dsonar.login=5de9dda11579f5779d84f0802ba80ab62399ecc1 \
  -Dsonar.exclusions=com/company/packageA/generated/**/*.java,com/company/packageB/generated/**/*.java

该种命令行指定了 sonar.host.url的,不需要单独在 ~/.m2/settings.xml 中再配置 sonar 的信息了。

gitlab 集成

#.gitlab-ci.yml
stages: 
- build 
build_master:
  image: maven
  stage: build
  artifacts:
    paths:
    - target/*.jar
  script:
  - mvn package sonar:sonar -Dsonar.host.url=http://192.168.116.82:9000/
  only:
  - master

使用 Sonar Scanner 分析代码

参考:

  1. 官网:https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner
  2. SonarQube Scanning in 15 Minutes
sonar-scanner \
  -Dsonar.projectKey= my-stinky-php-files \
  -Dsonar.sources=. \
  -Dsonar.host.://localhost:9000 \
  -Dsonar.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

如果发现

有数据但是点进去后并没有明细,尝试删除 ES 文件重启 sonar 服务

rm -rf sonarqube/data/es5

SonarQube Api 使用:https://codeen-app.euclid-ec.org/sonar/web_api/api/measures,可以使用 http://192.168.126.182:9000/api/measures/component?componentId=AWkUMtOgOkBh-huuQOcL&metricKeys=ncloc,complexity,violations,bugs 来获取一个项目的基本信息,用于生成一些自定义的报表 https://docs.sonarqube.org/latest/user-guide/metric-definitions/

SonarQube Webhooks

Administration -> Configuration -> Webhooks 配置回调地址,调用接口参数示例

{"serverUrl":"http://localhost:9000","taskId":"AWkzSF8Qt6GvzYFKix3r","status":"SUCCESS","analysedAt":"2019-02-28T16:45:58+0800","changedAt":"2019-02-28T16:45:58+0800","project":{"key":"cn.bjca.footstone:typhon","name":"typhon","url":"http://localhost:9000/dashboard?id=cn.bjca.footstone%3Atyphon"},"branch":{"name":"master","type":"LONG","isMain":true,"url":"http://localhost:9000/dashboard?id=cn.bjca.footstone%3Atyphon"},"qualityGate":{"name":"Sonar way","status":"OK","conditions":[{"metric":"new_reliability_rating","operator":"GREATER_THAN","value":"1","status":"OK","onLeakPeriod":true,"errorThreshold":"1"},{"metric":"new_duplicated_lines_density","operator":"GREATER_THAN","status":"NO_VALUE","onLeakPeriod":true,"errorThreshold":"3"},{"metric":"new_maintainability_rating","operator":"GREATER_THAN","value":"1","status":"OK","onLeakPeriod":true,"errorThreshold":"1"},{"metric":"new_coverage","operator":"LESS_THAN","status":"NO_VALUE","onLeakPeriod":true,"errorThreshold":"80"},{"metric":"new_security_rating","operator":"GREATER_THAN","value":"1","status":"OK","onLeakPeriod":true,"errorThreshold":"1"}]},"properties":{}}
[GIN] 2019/02/28 - 16:46:19 | 200 |     249.315µs |       127.0.0.1 | POST     /sonar
{"serverUrl":"http://localhost:9000","taskId":"AWkzTRMUt6GvzYFKix3u","status":"SUCCESS","analysedAt":"2019-02-28T16:51:08+0800","changedAt":"2019-02-28T16:51:08+0800","project":{"key":"cn.bjca.footstone:typhon","name":"typhon","url":"http://localhost:9000/dashboard?id=cn.bjca.footstone%3Atyphon"},"branch":{"name":"master","type":"LONG","isMain":true,"url":"http://localhost:9000/dashboard?id=cn.bjca.footstone%3Atyphon"},"qualityGate":{"name":"Sonar way custom","status":"ERROR","conditions":[{"metric":"new_reliability_rating","operator":"GREATER_THAN","value":"1","status":"OK","onLeakPeriod":true,"errorThreshold":"1"},{"metric":"new_duplicated_lines_density","operator":"GREATER_THAN","status":"NO_VALUE","onLeakPeriod":true,"errorThreshold":"3"},{"metric":"bugs","operator":"GREATER_THAN","value":"9","status":"ERROR","onLeakPeriod":false,"errorThreshold":"0"},{"metric":"new_maintainability_rating","operator":"GREATER_THAN","value":"1","status":"OK","onLeakPeriod":true,"errorThreshold":"1"},{"metric":"new_coverage","operator":"LESS_THAN","status":"NO_VALUE","onLeakPeriod":true,"errorThreshold":"80"},{"metric":"new_security_rating","operator":"GREATER_THAN","value":"1","status":"OK","onLeakPeriod":true,"errorThreshold":"1"}]},"properties":{}}
[GIN] 2019/02/28 - 16:51:27 | 200 |      97.476µs |       127.0.0.1 | POST     /sonar

google set in sonar.exclusions: file:**/test/**
Expected: To remove the directory from all code calculations
Actual: Is working as expected, the directory is removed from all calculations.

使用 SonarCloud 检测 Golang 代码, 并上传测试覆盖率到 codecov

.travis.yml

dist: trusty
# ...
addons:
  sonarcloud:
    organization: "your organization"
script:
  - go test -test.bench=.* -coverprofile=coverage.txt -covermode=atomic
  - sonar-scanner
after_success:
  - bash <(curl -s https://codecov.io/bash)

sonar-project.properties

# ...
sonar.go.coverage.reportPaths=coverage.txt

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

列表为空,暂无数据

关于作者

凝望流年

暂无简介

0 文章
0 评论
0 人气
更多

推荐作者

淹不死的鱼

文章 0 评论 0

zhangMack

文章 0 评论 0

爱的故事

文章 0 评论 0

linces

文章 0 评论 0

早乙女

文章 0 评论 0

鸵鸟症

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击“接受”或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。