测试左移:代码分析平台 SonarQube 实战


代码分析介绍

代码分析所关注的质量指标:

  • 代码坏味道
    • 代码规范
    • 技术债评估
  • bug 和漏洞
  • 代码重复度
  • 单测与集成
    • 测试用例数量
    • 覆盖率

常见代码分析工具:

  • 综合性的代码分析平台
    • SonarQube:支持自定义代码分析规则
      image
  • IDE 辅助功能
    • Xcode、Android Studio
    • 阿里巴巴 Java 开发手册:IDE 插件支持
  • 独立的静态分析工具
    • FindBugs、AndroidLint、ScanBuild
    • 阿里巴巴 Java 开发手册:PMD 插件

SonarQube 使用流程:

image


SonarQube 平台搭建

临时部署

# 自带小型内存级db
docker run -d \
    --name sonarqube_dev \
    -p 9000:9000 -p 9092:9092 \
    sonarqube

访问主机 IP:9000

image


正式部署

# 设置变量
db_instance=postgres_prod  # postgres 实例名称
sonarqube_instance=sonarqube_prod  # sonar 实例名称
data_dir=/root/sonarqube  # 数据挂载主目录
mkdir -p $data_dir

# 创建网络
docker network create sonarqube

# 启动 pg 数据库
docker run -d \
    --name $db_instance \
    --network sonarqube \
    -p 5432:5432 \
    -e POSTGRES_USER=sonarqube \
    -e POSTGRES_PASSWORD=sonarqube \
    -e PGDATA=/var/lib/postgresql/data/pgdata \
    -v $data_dir/postgresql:/var/lib/postgresql/data \
    postgres

# 创建数据目录
mkdir $data_dir/sonarqube_data  # 数据目录
mkdir $data_dir/sonarqube_extensions  # 扩展目录
mkdir $data_dir/sonarqube_logs  # 日志目录

# 启动 soarqube 时所需的配置
sysctl -w vm.max_map_count=524288
sysctl -w fs.file-max=131072
ulimit -n 131072
ulimit -u 8192

# 启动 soarqube 部署
docker run -d \
    --name $sonarqube_instance \
    --network sonarqube \
    -p 9000:9000 -p 9092:9092 \
    -e SONARQUBE_JDBC_USERNAME=sonarqube \
    -e SONARQUBE_JDBC_PASSWORD=sonarqube \
    -e SONARQUBE_JDBC_URL="jdbc:postgresql://$db_instance/sonarqube" \
    -v $data_dir/sonarqube_data:/opt/sonarqube/data \
    -v $data_dir/sonarqube_extensions:/opt/sonarqube/extensions \
    -v $data_dir/sonarqube_logs:/opt/sonarqube/logs \
    sonarqube

# 启动过程较慢,可以从日志查看启动进度
docker logs -f sonarqube

image


代码分析实战

Sonar 创建项目

Sonar 平台默认登录账号:admin/admin

image


image


image


image


填写任意字符后生成 Token(注意保存):

image

SONARQUBE_TOKEN=e74425b959d9b4666195d7278fafee8fac5d6a72

以 Maven 为例:

mvn clean verify sonar:sonar \  # sonar:sonar 需要先在本地maven中安装插件
  -Dsonar.projectKey=demo \
  -Dsonar.host.url=http://192.168.3.222:9000 \
  -Dsonar.login=e74425b959d9b4666195d7278fafee8fac5d6a72

image


image


开源项目演练

使用以下开源平台进行代码分析演练:

image

git clone https://github.com/linlinjava/litemall.git
cd litemall
# 打包项目
mvn clean package

SONARQUBE_TOKEN=e74425b959d9b4666195d7278fafee8fac5d6a72
# 使用 java 11
# 使用 sonar 对该项目代码进行分析,并上传结果到 sonar 平台中
mvn  sonar:sonar  \
  -Dsonar.host.url=http://192.168.3.222:9000 \
  -Dsonar.login=$SONARQUBE_TOKEN
  -Dsonar.projectKey=demo

image


在 sonar 平台上查看代码构建的分析概况:

image

  • bug:36 个
  • 漏洞:1 个
  • 安全漏洞:35 个
  • 技术债: 66 天
  • 代码不规范问题:22000 + 个
  • 没有进行单元测试
  • 有重复代码

代码构建-分析明细:

image

空指针分析:

image


单元测试-代码覆盖率实战

非侵入式的生成 jacoco 代码覆盖率数据:

# 查找生成的 jacoco 覆盖率数据文件路径
find $PWD -name "jacoco.*"

mvn clean \
  org.jacoco:jacoco-maven-plugin:0.8.6:prepare-agent \
  test \
  org.jacoco:jacoco-maven-plugin:0.8.6:report  \
  sonar:sonar  \
  -Dsonar.host.url=http://192.168.3.222:9000  \
  -Dsonar.login=$SONARQUBE_TOKEN  \
  -Dsonar.projectKey=demo  \
  -Dsonar.coverage.jacoco.xmlReportPaths="$PWD/**/**/**/**/jacoco.xml" \
  -Dmaven.test.failure.ignore=true  \
  -Dmaven.test.skip=false
  • 以上命令表示:先进行编译单测生成覆盖率数据,再将覆盖率数据上传到 sonar 上。
  • 使用通配符匹配所有 jacoco 报告,则 sonar 还会统计每次新增代码的覆盖率及其趋势图。
  • 关键数据:
    • 覆盖率报告:**/jacoco
    • 覆盖率原始 dump 数据:**/jacoco.exec

image

image


另一种做法:侵入式的生成 jacoco 代码覆盖率数据

  • 在 pom 中增加 jacoco 插件
  • mvn clean test jacoco:report

集成测试-代码覆盖率实战

做法:

  1. 使用 jacoco 的 tcp 模式。
  2. 生成覆盖率数据:
    • 精准测试做法:在每次集成测试的用例之后(teardown)获取覆盖率数据并重置覆盖率数据。
    • 传统覆盖率做法:在所有集成测试的用例之后(teardown_session)中获取覆盖率数据。
  3. 覆盖率数据合并(merge)。
  4. 将覆盖率数据 report 生成 xml 文件。
  5. 上传 Java 相关(单测)测试数据到 sonar,可使用 sonar.junit.reportPaths、sonar.coverage.jacoco.xmlReportPaths 参数。
  6. 上传集成测试执行数据与覆盖率数据到 sonar,则可使用 sonar.testExecutionReportPaths、sonar.coverageReportPaths 参数。

示例:在进行集成测试(生成覆盖率数据)后,再利用 scanner 上传覆盖率数据到 sonar 上

# 查找 jacoco 覆盖率数据文件所在路径
find $PWD -name "jacoco.*"
# 上传覆盖率数据到 sonar
mvn \
  sonar:sonar  \
  -Dsonar.host.url=http://192.168.3.222:9000  \
  -Dsonar.login=$SONARQUBE_TOKEN  \
  -Dsonar.projectKey=demo  \
  -Dsonar.coverage.jacoco.xmlReportPaths="$PWD/**/**/**/**/jacoco.xml" \
  -Dmaven.test.failure.ignore=true   \
  -Dmaven.test.skip=false
posted @ 2022-06-29 23:51  Juno3550  阅读(594)  评论(0编辑  收藏  举报