22

我是新手。我正在使用下面的代码。但它会生成单元测试用例的覆盖率。但它没有为集成测试用例生成。我在包 src/test/java 中有我的测试类。

test {
    dependsOn jettyRunWar
    ignoreFailures true
    finalizedBy jettyStop
}

apply plugin: 'jacoco'

jacocoTestReport {
    group = "Reporting"
    description = "Generate Jacoco coverage reports after running tests."
    additionalSourceDirs = files(sourceSets.main.allJava.srcDirs)
}
4

4 回答 4

18

EDIT4Gradle 7.4 RC1 发行说明表明 gradle 现在可以为 JUnit 和 JaCoCo 生成单个报告文件。这将避免下面解释的脆弱配置。

您所要做的就是应用相关的插件

目前(7.4 RC1)的当前缺点是仅支持 HTML 报告。并且这些聚合任务与JVM 测试套件插件(但由插件自动添加java)协同工作。

因此,请在下一个版本中关注此功能。

使用 Gradle 5.4.1(现在是 5.5.1),我能够在任何测试任务之后获得报告,目前我同时拥有testintegrationTest任务。

EDIT3:修复了仅执行一些测试任务时的潜在错误

  • 不要executionDatadoLast/doFirst块中配置,这是我的错误。有关更多信息,请查看此gradle github 票
  • 添加了更谨慎的选择(同样不在doLast/doFirst块中) executionData { tasks.withType(Test).findAll { it.jacoco.destinationFile.exists() }*.jacoco.destinationFile }

EDIT2:解决方案是一样的,我只是调整了一下

  • 要使用的报告目的地jacoco.reportsDir
  • executionData 现在需要tasks.withType(Test)而不是仅仅[test, integrationTest]
  • 设置executionData是在doFirst块中完成的,而不是doLast

编辑:查看文档后JacocoReport,有一个变体JacocoReport:executionData直接接受 Gradle 任务。它之所以有效,是因为JaCoCo 插件JacocoTaskExtension为所有类型的任务添加了扩展Test。这样就不容易出错。


jacocoTestReport {
    // The JaCoCo plugin adds a JacocoTaskExtension extension to all tasks of type Test.
    // Use task state to include or not task execution data
    // https://docs.gradle.org/current/javadoc/org/gradle/api/tasks/TaskState.html
    // This declaration will be used as a closure, notice there no wrapping parenthesis
    executionData tasks.withType(Test).findAll { it.state.executed }
    
    // If the above instruction really don't work, there maybe some things that intervene in the process, in this case, you may be a bit more lucky with this instruction
    // executionData { tasks.withType(Test).findAll { it.jacoco.destinationFile.exists() }*.jacoco.destinationFile }

    reports {
        xml.enabled true
        xml.destination(file("${jacoco.reportsDir}/all-tests/jacocoAllTestReport.xml"))
        html.enabled true
        html.destination(file("${jacoco.reportsDir}/all-tests/html"))
    }
}

同样的技巧也可以应用于sonarqubetask :

sonarqube {
    group = "verification"
    properties {
        // https://jira.sonarsource.com/browse/MMF-1651
        property "sonar.coverage.jacoco.xmlReportPaths", jacocoTestReport.reports.xml.destination
        properties["sonar.junit.reportPaths"] += integrationTest.reports.junitXml.destination
        properties["sonar.tests"] += sourceSets.integrationTest.allSource.srcDirs
        // ... other properties
    }
}

较旧但非常有效的答案。同样使用上述知识(Test任务由 扩展JacocoTaskExtension),可以替换by和的手动file配置。executionDatatest.jacoco.destinationFileintegrationTest.jacoco.destinationFile

// Without it, the only data is the binary data, 
// but I need the XML and HTML report after any test task
tasks.withType(Test) {
    finalizedBy jacocoTestReport
}

// Configure the report to look for executionData generated during the test and integrationTest task
jacocoTestReport {
    executionData(file("${project.buildDir}/jacoco/test.exec"),
                  file("${project.buildDir}/jacoco/integrationTest.exec"))
    reports {
        // for sonarqube
        xml.enabled true
        xml.destination(file("${project.buildDir}/reports/jacoco/all-tests/jacocoAllTestReport.xml"))
        // for devs
        html.enabled true
        html.destination file("${project.buildDir}/reports/jacoco/all-tests/html")
    }
}


sonarqube {
    group = "verification"
    properties {
        // https://jira.sonarsource.com/browse/MMF-1651
        property "sonar.coverage.jacoco.xmlReportPaths", ${project.buildDir}/test-results/integrationTest"
        properties["sonar.junit.reportPaths"] += "${project.buildDir}/test-results/integrationTest"
        properties["sonar.tests"] += sourceSets.integrationTest.allSource.srcDirs
        // ... other properties
    }
}

project.tasks["sonarqube"].dependsOn "jacocoTestReport"
于 2019-08-02T16:08:01.583 回答
7

我相信最完整的答案将如下所示:

tasks.withType(Test) {
    finalizedBy jacocoTestReport
}

project.jacocoTestReport {
    getExecutionData().setFrom(fileTree(buildDir).include("/jacoco/*.exec"))

    reports {
        csv.enabled true
    }
}

至少它完全适合我的集成和功能测试需求。

于 2019-12-17T15:08:52.107 回答
4

看起来,您需要告诉 build.gradle 是使用 sourceSets 的集成测试(即包含这些 IT 测试的文件夹)在哪里。就我而言,我在 src/java 下有源代码(而不是 src/main/java - gradle 默认)。我的单元测试(Junit)在 test/java 文件夹下,我的集成测试在 src/java-test 文件夹下。

sourceSets {
   main {
      java {
         srcDir 'src/java'
      }
   }
   test {
      java {
         srcDir 'test/java'
      }
      resources {
         srcDir 'test/resources'
         srcDir 'conf'
      }
   }
   integrationTest {
      java {
         srcDir 'src/java-test'
      }
   }
}

然后,我将 integrationTest 任务设置为 ... 你可以调整它,因为你可能没有 cleanTest (我创建的自定义任务),所以你可以忽略这个dependsOn ...我认为在你的情况下你会使用像 jettyStart 这样的东西当您将其用于 IT 测试时(启动容器以运行 IT 测试,然后 finalizedBy 功能停止 jetty .. jetty 插件)

task integrationTest( type: Test, dependsOn: cleanTest ) {
   jacoco {
      //destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
      destinationFile = file("$buildDir/jacoco/integrationTest.exec")
      //classDumpFile = file("$buildDir/jacoco/classpathdumps")
      classDumpFile = file("$buildDir/classes/integrationTest")
   }
   testClassesDir = sourceSets.integrationTest.output.classesDir
   classpath = sourceSets.integrationTest.runtimeClasspath
}

请参阅这篇文章,了解我最后拥有的更详细的输出结构和脚本。我为单元测试(test.exec)和 IT 测试 intergrationTest.exec 获取了 .exec。但我没有为这两个测试获取 jacoco.xml/jacocoHtml 报告。我还发现,如果我运行“gradle clean build”(包括对“test”任务的调用)和“gradle clean build integrationTest”,那么稍后会覆盖 build/test-results 文件夹和 build/reports/ 中的单元测试数据测试文件夹。

Jacoco 单元和集成测试覆盖范围 - 个人和整体

注意:在我的情况下,jacocoTestReport 是在通用 gradle 文件之一的全局 gradle init.d 文件夹中定义的。这将帮助我们不在项目级别的 build.gradle 文件的所有 / 中包含相同的代码。

于 2013-09-26T15:57:19.847 回答
4

由于我无法使用任何答案运行它,因此我将在此处添加我的解决方案。如果您integTest先运行测试任务(例如)然后调用它,它将起作用jacocoTestReport

您只需要告诉jacocoTestReport任务在哪里可以找到从您的测试任务收集的执行数据。执行数据始终以测试任务命名。因此,如果您有一个名为的测试任务integTest,您的执行数据将存储在build/jacoco/integTest.exec. 该jacocoTestReport任务也可以通过将它们添加到属性 executionData 来配置为查找那些其他文件。您还可以添加通配符包含,以便考虑所有执行数据:

jacocoTestReport {
    executionData = fileTree(dir: project.projectDir, includes: ["**/*.exec"])
}

更新 正如@rahulmohan 所述, executionData 属性已变为只读。而是如下定义 jacocoTestReport 任务:

jacocoTestReport {
    getExecutionData().from(fileTree(project.projectDir).include("/jacoco/*.exec"))

通过执行下面的语句,将为您创建集成测试任务(例如integTest)的测试覆盖率 jacoco 报告

./gradlew integTest jacocoTestReport

这也适用于要在模块中运行integTest任务的多模块项目a

./gradlew a:integTest a:jacocoTestReport
于 2020-01-22T13:46:25.263 回答