繁体   English   中英

使用 JaCoCo 和 Gradle 的离线仪器

[英]Offline instrumentation with JaCoCo and Gradle

我在这里遇到了很多人遇到的同样问题,即在使用 Jacoco/Gradle 和 Powermock 时获得正确的代码覆盖率信息。

我已经阅读了这里和其他地方的所有各种线程,并且我成功地创建了一个任务(对于 Gradle 6.4),它对我的项目类进行离线检测。 作为参考,执行此操作的代码如下:

task instrumentClasses(dependsOn: [ classes, project.configurations.jacocoAnt ]) {
    inputs.files classes.outputs.files
    File outputDir = new File(project.buildDir, 'instrumented')
    outputs.dir outputDir
    doFirst {
        project.delete(outputDir)
        ant.taskdef(
                resource: 'org/jacoco/ant/antlib.xml',
                classpath: project.configurations.jacocoAnt.asPath,
                uri: 'jacoco'
        )
        def instrumented = false
        jacocoOfflineSourceSets.each { sourceSetName ->
            if (file(sourceSets[sourceSetName as String].output.classesDirs.singleFile.absolutePath).exists()) {
                def instrumentedClassedDir = "${outputDir}/${sourceSetName}"
                ant.'jacoco:instrument'(destdir: instrumentedClassedDir) {
                    fileset(dir: sourceSets[sourceSetName as String].output.classesDirs.singleFile, includes: '**/*.class')
                }
                //Replace the classes dir in the test classpath with the instrumented one
                sourceSets.test.runtimeClasspath -= sourceSets[sourceSetName as String].output.classesDirs
                sourceSets.test.runtimeClasspath += files(instrumentedClassedDir)
                instrumented = true
            }
        }
        if (instrumented) {
            //Disable class verification based on https://github.com/jayway/powermock/issues/375
            test.jvmArgs += '-noverify'
        }
    }
}

现在,在大多数情况下,这似乎工作正常。 我已成功验证我的课程现在已正确配置,并且我看到 Jacoco 生成的报告包含正确的信息。 问题是尽管我的 SonarQube 服务器仍然将有问题的类列为未涵盖的类。 关于这一点,我不知道我需要做什么来解决它。

作为参考,我正在使用以下版本的 sonarqube 插件:

"org.sonarqube" version "2.7"

我的 CI 以下列方式运行 Gradle 任务:

 - ./gradlew jacocoTestReport sonarqube ${SONAR_GRADLE_EXTRA_PARAMS} -Dsonar.projectKey=${CI_PROJECT_ID} -Dsonar.host.url=${SONAR_URL} -Dsonar.login=${SONAR_LOGIN} -Dsonar.branch.name=${CI_COMMIT_REF_NAME};

我确实知道它一定是 SonarQube 或我运行 Gradle 任务的方式的一些配置问题,但我不确定罪魁祸首是什么。

如果您能够生成聚合的 jacoco 报告(从所有源集聚合),那么您可以在运行时在 sonarqube 任务中简单地指定(并且声纳只会选择 jacoco 计算的确切覆盖率信息)

./gradlew sonarqube -Dsonar.host.url=https://sonarcloud.io -Dsonar.login=XXXX -Dsonar.organization=XXXXX -Dsonar.coverage.jacoco.xmlReportPaths=build/jacoco-report.xml

仅供参考,我正在 build/jacoco-report.xml 创建汇总报告

下面是我的 gradle 配置(可能对你有用)

plugins {
  id 'org.springframework.boot' version '2.3.1.RELEASE'
  id 'io.spring.dependency-management' version '1.0.9.RELEASE'
  id 'java'
  id 'jacoco'
  id "org.sonarqube" version "2.8"
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_11

repositories {
  mavenCentral()
}

sourceSets {
  intTest {
    compileClasspath += sourceSets.main.output + sourceSets.test.output
    runtimeClasspath += sourceSets.main.output + sourceSets.test.output
  }
}

configurations {
  intTestImplementation.extendsFrom testImplementation
  intTestRuntimeOnly.extendsFrom testRuntimeOnly
}

dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-web'

  testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
  useJUnitPlatform()
  testLogging.showStandardStreams = true //To print logs
}


task integrationTest(type: Test) {
  testClassesDirs = sourceSets.intTest.output.classesDirs
  classpath = sourceSets.intTest.runtimeClasspath
  shouldRunAfter test
  testLogging.showStandardStreams = true //To print logs
}

jacocoTestReport {
  executionData(file("${project.buildDir}/jacoco/test.exec"), file("${project.buildDir}/jacoco/integrationTest.exec"))
  reports {
    xml.enabled true
    csv.enabled false
    xml.destination file("${buildDir}/jacoco-report.xml")
    html.destination file("${buildDir}/jacocoHtml")
  }
  mustRunAfter(test, integrationTest) // integration tests are required to run before generating the report
}

jacocoTestCoverageVerification {
  executionData(file("${project.buildDir}/jacoco/test.exec"), file("${project.buildDir}/jacoco/integrationTest.exec"))
  violationRules {
    rule {
      limit {
        counter = 'INSTRUCTION'
        minimum = 0.94
      }
      limit {
        counter = 'BRANCH'
        minimum = 1.0
      }
    }
  }
}

check.dependsOn(integrationTest, jacocoTestCoverageVerification)

tasks.withType(Test) {
  finalizedBy jacocoTestReport
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM