Android代码质量管理平台搭建

Jacoco & SonarQube

  • JaCoCo是一个Java代码覆盖率库,它可以帮助开发人员了解他们的代码库中哪些代码已经被测试覆盖,哪些代码还需要进行测试。JaCoCo可以与各种构建工具(如Maven和Gradle)集成,以生成代码覆盖率报告。
  • SonarQube是一个开源的代码质量管理平台,它可以帮助开发人员在整个开发周期中管理和提高代码质量。SonarQube可以与各种编程语言(如Java、C#、JavaScript等)集成,并提供了一系列功能,包括代码质量分析、代码覆盖率、代码复杂度、代码重复性、安全漏洞等方面的检测。 我们要利用这2个工具平台,使用构建工具Gradle给Android项目打造一个可视化代码覆盖率,首先,使用JaCoCo生成代码覆盖率报告,然后将报告传递给SonarQube进行分析。SonarQube将使用这些报告来提供更广泛的代码质量分析,包括代码复杂度、代码重复性、安全漏洞等方面的检测。

Jacoco集成到Gradle

  1. 添加plugin classpath "org.jacoco:org.jacoco.core:0.8.10"

  2. 创建一个jacoco.gradle文件在需要单元测试覆盖的module里面

  3. 粘贴和修改如下代码,注意可以配置输出报告忽略文件和文件夹的覆盖率,通常是View层和一些工具类等

    groovy 复制代码
     apply plugin: "jacoco"
    
     jacoco {
         toolVersion = '0.8.10'
     }
    
     // 配置需要忽略单元测试覆盖率的文件或文件夹
     //* 匹配零个或多个字符
     //** 匹配零个或多个目录
     //? 匹配单个字符
     project.ext.coverageExclusions = [
             '**/BR.*',
             '**/R.*',
             '**/R$*.*',
             '**/Manifest*.*',
             "**/*Test*.*",
             '**/BuildConfig.*'
     ]
    
     def javaDebugTree = fileTree(dir: "${buildDir}/intermediates/javac/debug", excludes: coverageExclusions)
     def kotlinDebugTree = fileTree(dir: "${buildDir}/tmp/kotlin-classes/debug", excludes: coverageExclusions)
    
     task jacocoTestReport(type: JacocoReport, dependsOn: "testDebugUnitTest") {
         group = "Reporting"
         description = "Generate Jacoco coverage reports after running tests."
    
         reports {
             xml.getRequired().set(true)
             html.getRequired().set(true)
         }
    
         sourceDirectories.from = files(["${project.projectDir}/src/main/java"])
         classDirectories.from = files([javaDebugTree, kotlinDebugTree])
    
         // pattern '**/*' searches execution data in all sub-directories of build
         def execDataPatterns = ["**/*.exec", "**/*.ec"]
         executionData.from = files(fileTree(dir: "build", includes: execDataPatterns))
     }
  4. 在需要的module的build.gradle中添加apply from: "jacoco.gradle"

  5. 执行命令 ./gradlew :module clean jacocoTestReport

  6. 单元测试全部成功后,检查文件夹 build/reports/jacoco/jacocoTestReport/是否存在

  7. 右键build/reports/jacoco/jacocoTestReport/html/index.html Open in -> Browser

  8. 根据包名展示当前代码覆盖的详细情况,点击包名可以查看java类的详情

SonarQube安装和部署

  1. 下载免费的社区版Community Edition: www.sonarqube.org/downloads/
  2. 检查是否安装和配置JDK的环境变量
  3. 解压并且打开目录/bin,控制台打开/bin/目录选择操作系统对应文件夹进入
  4. 在控制台执行启动命令 ./sonar.sh start,支持命令 { console | start | stop | force-stop | restart | status | dump }
  5. 浏览器输入127.0.0.1:9000进入登录页面,默认账户密码 admin/admin
  6. 生成 api Token, 右上角我的账户-> security -> Generate Tokens

SonarQube集成到Gradle

  1. 添加plugin

    groovy 复制代码
     dependencies {
         classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.0"
     }
  2. 在根目录build.gradle配置,把Jacoco的report输出路径配置到jacoco.xmlReportPaths

    groovy 复制代码
    apply plugin: 'org.sonarqube'
    sonarqube {
        properties {
            property "sonar.projectName", "MVI-Hilt"
            property "sonar.projectKey", "MVI-Hilt"
            property "sonar.modules", ":app, :mvi"
            property "sonar.host.url", "http://127.0.0.1:9000"
            property "sonar.token", "squ_11f5a8e2654358fefc45420da045f50ab2dde76b"
            property "sonar.sources", "src/main/java, src/debug/java"
            property "sonar.tests", "src/test/java, src/androidTest/java"
            property "sonar.binaries", "build/intermediates/javac/debug/classes"
            property "sonar.androidLint.reportPaths", "build/reports/lint-results.xml"
            property "sonar.java.coveragePlugin", "jacoco"
            property "sonar.kotlin.coveragePlugin", "jacoco"
            property "sonar.junit.reportsPath", "build/reports/tests"
            property "sonar.coverage.jacoco.xmlReportPaths", "build/reports/coverage/debug/report.xml, build/reports/jacoco/jacocoTestReport/jacocoTestReport.xml"
        }
    }
  3. 在Android Studio中直接点击sonarqube {...}左边的绿色➡️,或者在控制台运行 ./gradlew sonarqube

  4. 浏览器打开网页http://127.0.0.1:9000

  5. 点击项目可以查看扫描的报告详情,代码规范(code smell);代码漏洞;覆盖率;代码重复率等

  6. 项目配置github actions 或者jenkins ci/pipeline等,在提交PR之后PR中输出一份当前PR代码的报告,帮助Reivewer来检查当前代码是否有漏洞和代码规范问题。

Issue集锦

  1. 执行Task:sonarqube显示成功却没有任何反应,日志中输出Skipping SonarQube analysis: no properties configured, was it skipped in all projects? 解决方案:gradle.properties中删除org.gradle.unsafe.configuration-cache=true
  2. 执行Task: 报错 Can't add different class with same name: com/example/Xxx 解决方案:把报错的这个Class配置到 jacoco的Exclusions中,'com/example/**'

扩展阅读

代码质量管理,我们需要编写单元测试代码,之前的MVI系列文档中详细的介绍了Android中如何实现单元测试。另外在国内Android对单元测试等并没有很强的要求,很多开发者并不会写单元测试,这个时候官方的文档其实是最新和最权威,合适的学习途径也让我们事半功倍。 Android的MVI架构最佳实践(四):单元测试 - 掘金 (juejin.cn)

相关推荐
玖釉-3 分钟前
解决PowerShell执行策略导致的npm脚本无法运行问题
前端·npm·node.js
Larcher36 分钟前
新手也能学会,100行代码玩AI LOGO
前端·llm·html
雨白1 小时前
重识 Java IO、NIO 与 OkIO
android·java
徐子颐1 小时前
从 Vibe Coding 到 Agent Coding:Cursor 2.0 开启下一代 AI 开发范式
前端
小月鸭1 小时前
如何理解HTML语义化
前端·html
jump6801 小时前
url输入到网页展示会发生什么?
前端
诸葛韩信1 小时前
我们需要了解的Web Workers
前端
啦啦9117142 小时前
Niagara Launcher 全新Android桌面启动器!给手机换个门面!
android·智能手机
brzhang2 小时前
我觉得可以试试 TOON —— 一个为 LLM 而生的极致压缩数据格式
前端·后端·架构
游戏开发爱好者82 小时前
iOS 上架要求全解析,App Store 审核标准、开发者准备事项与开心上架(Appuploader)跨平台免 Mac 实战指南
android·macos·ios·小程序·uni-app·iphone·webview