前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Sonar Scanner系列之架构与Java篇

Sonar Scanner系列之架构与Java篇

作者头像
Criss@陈磊
发布2019-10-22 14:15:45
4.8K1
发布2019-10-22 14:15:45
举报
文章被收录于专栏:测试技术圈测试技术圈

本文系列将介绍Sonar在实际工程项目中落地的场景,例如: 1)多语言项目的扫描,如JAVA/JS/C++/C#/PLSQL 2)多分支扫描 3)覆盖率如何统计 等等。 不在讨论范围内的问题 1)自定义扫描规则? 2)扫出来的问题,怎么让开发及时修复? 本文作为开篇,将介绍 1)Sonar Scanner的工作机制, 2)Java项目中利用 Maven的Sonar Scanner 插件进行扫描的配置和步骤 3)使用Token,多Module项目扫描和忽略等一些实际问题。

与Jenkins不同的工作机制

与Jenkins类似,SonarQube也是一个C/S架构的服务。根据其官网所述,是以下的一个架构。 包括了:

  1. SonarQube服务端: 主要包括以下三部分
    • Web服务器
    • 搜索引擎-Elasticsearch to back searches from the UI
    • 后台计算服务-连接数据库
  2. 后台数据库:
    • SonarQube实例的配置信息,如安全、插件等
    • 项目、视图的质量快照数据
  3. SonarQube Plugin 安装在服务端的插件,例如语言包、SCM、认证、治理等等
  4. SonarScanner 在构建和持续集成服务器上执行并分析项目

image.png

这其中Sonar Scanner是本文所要介绍的主角。通过上述架构图中的数据流转方向,我们可以了解到Sonar和Jenkins的一个很大的不同。也就是Sonar中的客户端(Scanner)只负责数据的上报,它可以自行触发扫描,并不接受来自服务端的指令,不像Jenkins的Agent受到服务端的任务触发后才会执行。笔者在设计测试用例管理系统时,也参考了类似这样的架构,让测试用例执行的起点由客户端自行控制,只要将最终结果汇报上来即可。

解决方案一览

在公司的产品线中,既有核心的实时类C/C++程序,也有传统的C#前台+SP后台的遗留系统。目前也正在实现微服务转型,JAVA和前端JS类项目也日益多了起来。因此,我们的SonarQube质量检测服务,需要支持上述所有的类型。而根据Sonar官方提供的方案,需要用到如下的Scanner 在实践中也发现,Sonar Scanner以同一次扫描结果作为一个SonarQube Project的范围。即使指定了相同的Project Key,不同扫描器的扫描结果只会互相覆盖。因此,由于扫描器的不同,一个包含了C#、C++和PLSQL的项目,很不幸需要被三个扫描器各自扫描一次,同时生成三个SonarQube project来呈现扫描结果。 本文将分别介绍上述语言的项目中,如何利用Scanner来进行扫描。

image.png

JAVA类的项目

假设项目中使用的是Maven作为构建工具。配套的,我们通过SonarQube官方提供的SonarQube Scanner for Maven这个插件来进行代码的扫描,如果还要得到单元测试和代码覆盖率报告,那么还需要使用Maven Surefire插件以及Jacoco这样的覆盖率统计工具。 接下来逐一介绍下。

1、指定SonarQube服务器地址和口令

整个方案的基础是,让Maven中的Sonar Scanner插件能知道SonarQube服务器和登录口令。修改maven配置文件$MAVEN_HOME/conf/settings.xml 或者 ~/.m2/settings.xml。 文件的访问顺序是:~/.m2/settings.xml优先,若无此文件,maven自动去读$MAVEN_HOME/conf/settings.xml

代码语言:javascript
复制
 <profiles>                       
<profile>                             
<id>sonar</id>                            
     <activation> 
            <activeByDefault>true</activeByDefault>
       </activation>                            
 <properties>                                    
      <sonar.host.url>http://IP:PORT </sonar.host.url>
<sonar.login>TOKEN </sonar.login>
</properties>                   
</profile>              
 </profiles>

另外,配置了sonar.login使用TOKEN后,不要再配置sonar.password了,不然sonar scanner会将token作为用户名去登录,导致用户名密码不匹配登陆失败。Token产生,可以参见SonarQube使用说明。需要注意的是,这个token的生成是被设计为“阅后即焚”的。在SonarQube页面上生成并关闭后,再也无法看到了,需要注意保存,否则只能再次生成了。

2、引入指定Sonar Scanner for Maven的Maven插件

方法一(推荐):修改工程的pom.xml。

代码语言:javascript
复制
            <build>
                 <pluginManagement>
                     <plugins>
                        ......
                          <plugin>
                                 <groupId>org.sonarsource.scanner.maven</groupId>
                                 <artifactId>sonar-maven-plugin</artifactId>
                                 <version>3.6.0.1398</version>
                          </plugin>
                     </plugins>
                </pluginManagement>
           </build>

方法二: 修改maven配置文件$MAVEN_HOME/conf/settings.xml 或者 ~/.m2/settings.xml。(~/.m2/settings.xml优先,若无此文件,maven自动去读$MAVEN_HOME/conf/settings.xml )

代码语言:javascript
复制
               <pluginGroups>
   <pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
              </pluginGroups>
3、配置单元测试执行报告的路径

配置单元测试执行报告的路径,修改最外层pom.xml 场景一:单个module工程

代码语言:javascript
复制
 <properties>
  .......
  <sonar.jacoco.reportPaths>
        ${project.basedir}/target/jacoco.exec
   </sonar.jacoco.reportPaths>
 </properties>

场景二:多个modules工程

代码语言:javascript
复制
  <properties>
   .......
   <sonar.jacoco.reportPaths>
        ${project.basedir}/../target/jacoco.exec
  </sonar.jacoco.reportPaths>
 </properties>
4、配置单元测试覆盖率统计插件jacoco

这个配置在网上很容易找到,为了内容的完整性还是放一下。功能就是把jacoco 挂载到maven 的各个phase/goal上去,如在单元测试和集成测试时,实现jacoco的插桩。

代码语言:javascript
复制
                     <profiles>
                          <profile>
                                <id>sonar-coverage</id>
                                        <activation>
<activeByDefault>false</activeByDefault>
                                        </activation>
                                        <build>
                <pluginManagement>
                           <plugins>
                                     <plugin>
<groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
                   <version>0.8.2</version>
                         </plugin>
                               </plugins>
                               </pluginManagement>
                                <plugins>
                                       <plugin>
 <groupId>org.jacoco</groupId>
               <artifactId>jacoco-maven-plugin</artifactId>
<configuration>                                                                      <destFile>${sonar.jacoco.reportPaths}</destFile>
         <append>true</append>
                          </configuration>
                                      <executions>
                                               <execution>
                                                   <id>agent-for-ut</id>
                                                       <goals>
              <goal>prepare-agent</goal>
                                        </goals>
                                              </execution>
                                         <execution>
                                                <id>agent-for-it</id>
                                                       <goals>
                      <goal>prepare-agent-integration</goal>
                                     </goals>
                                                </execution>
                                        <execution>
                                          <id>jacoco-site</id>
                        <phase>verify</phase>
                                       <goals>
                                    <goal>report</goal>
                                            </goals>
                                    </execution>
                                            </executions>
                                     </plugin>
                                        </plugins>
                                   </build>
                                </profile>
                          </profiles>

如果需要实现集成测试/系统测试的代码覆盖率的话,则需要通过tcp等方式去dump覆盖率结果。这块不是本文的范围,就不展开了。

5、实施扫描

如果启用了分支,就需要分两次执行扫描。如果未使用的话,则一次扫描即可。 第一次扫描,先初始化执行master分支扫描 构建步骤增加 ”mvn sonar:sonar 不指定分支名字,默认是将扫描结果归属到master分支。 第二次扫描,指定分支名称 ”mvn sonar:sonar -Dsonnar.branch.name=${branchName}“** 如果挂载到了maven某个生命周期的某个阶段上,则执行 mvn clean install也可实现上述目的。

6、杂项
  1. 若只想做静态代码扫描,不执行测试用例和覆盖率,则在 mvn clean compile后执行sonar即可。

2)为了确保工程有单元测试执行结果,以便于让Sonar统计测试结果,需要忽略失败的测试结果,强制让Maven surefire插件生成测试报告 mvn clean test -Dmaven.test.failure.ignore=true 注意一定要加****-Dmaven.test.failure.ignore=true* **参数哦。

  1. 如何忽略用例, a) 忽略某个modules工程,在该module下配置 <sonar.skip>true</sonar.skip> 即可 b) 忽略如测试用例或其它某些package或.java文件,则配置<sonar.exclusions>[...]</sonar.exclusions>。

【未完待续】 1)如果一个项目中包含C++/C#/PLSQL多种语言,如何实施SonarQube扫描?需要扫几次,是几个项目? 2)社区版本的SonarQube没有扫描C++/PLSQL等语言的能力,怎么办? 3)如果代码库有多个分支,如何为每个分支产生扫描结果?社区版好像没有这个功能哎,怎么办? 4)为什么C++项目扫出来缺陷、安全漏洞都是0?覆盖率也是0%?

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

本文分享自 质问 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 与Jenkins不同的工作机制
  • 解决方案一览
    • JAVA类的项目
      • 1、指定SonarQube服务器地址和口令
      • 2、引入指定Sonar Scanner for Maven的Maven插件
      • 3、配置单元测试执行报告的路径
      • 4、配置单元测试覆盖率统计插件jacoco
      • 5、实施扫描
      • 6、杂项
相关产品与服务
持续集成
CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档