首页 文章

使用JaCoCo Gradle插件的Android测试代码覆盖率

提问于
浏览
32

我是Gradle和Android测试的新手,但我已经将我的Android项目转换为使用Gradle构建 .

现在,我正在尝试使用Gradle的JaCoCo插件执行Android项目的测试覆盖 .

我已将以下内容添加到build.gradle文件中:

apply plugin: 'jacoco'

当我运行“gradle jacocoTestReport”时出现以下错误:

Task 'jacocoTestReport' not found in root project '<project name>'.

从文档我应该也应用插件'java'但它与插件'android'冲突 .

有没有解决的办法?

提前致谢 .

4 回答

  • 0

    这是我如何使用 Jacoco

    buildscript {
      repositories {
        mavenLocal()
        mavenCentral()
      }
      dependencies {
        classpath 'com.android.tools.build:gradle:0.12.+'
        classpath 'org.robolectric:robolectric-gradle-plugin:0.11.+'
      }
    }
    
    apply plugin: 'com.android.application'
    apply plugin: 'robolectric'
    apply plugin: 'jacoco'
    
    android {
      compileSdkVersion 20
      buildToolsVersion "20.0.0"
    
      defaultConfig {
        applicationId "YOUR_PACKAGE_NAME"
        minSdkVersion 10
        targetSdkVersion 20
        testHandleProfiling true
        testFunctionalTest true
      }
      buildTypes {
        debug {
          testCoverageEnabled false
        }
        release {
          runProguard false
          proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
      }
      jacoco {
        version "0.7.1.201405082137"
      }
      packagingOptions {
        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/dependencies.txt'
        exclude 'META-INF/LGPL2.1'
        exclude 'META-INF/services/javax.annotation.processing.Processor'
        exclude 'LICENSE.txt'
      }
    }
    
    robolectric {
      include '**/*Test.class'
      exclude '**/espresso/**/*.class'
    
      maxHeapSize "2048m"
    }
    
    jacoco {
      toolVersion "0.7.1.201405082137"
    }
    
    // Define coverage source.
    // If you have rs/aidl etc... add them here.
    def coverageSourceDirs = [
        'src/main/java',
    ]
    
    task jacocoTestReport(type: JacocoReport, dependsOn: "connectedDebugAndroidTest") {
      group = "Reporting"
      description = "Generate Jacoco coverage reports after running tests."
      reports {
        xml.enabled = true
        html.enabled = true
      }
      classDirectories = fileTree(
          dir: './build/intermediates/classes/debug',
          excludes: ['**/R*.class',
                     '**/*$InjectAdapter.class',
                     '**/*$ModuleAdapter.class',
                     '**/*$ViewInjector*.class'
          ])
      sourceDirectories = files(coverageSourceDirs)
      executionData = files("$buildDir/jacoco/testDebug.exec")
      // Bit hacky but fixes https://code.google.com/p/android/issues/detail?id=69174.
      // We iterate through the compiled .class tree and rename $$ to $.
      doFirst {
        new File("$buildDir/intermediates/classes/").eachFileRecurse { file ->
          if (file.name.contains('$$')) {
            file.renameTo(file.path.replace('$$', '$'))
          }
        }
      }
    }
    
    
    dependencies {
      androidTestCompile('junit:junit:4.11') {
        exclude module: 'hamcrest-core'
      }
      androidTestCompile('org.robolectric:robolectric:2.3') {
        exclude module: 'classworlds'
        exclude module: 'maven-artifact'
        exclude module: 'maven-artifact-manager'
        exclude module: 'maven-error-diagnostics'
        exclude module: 'maven-model'
        exclude module: 'maven-plugin-registry'
        exclude module: 'maven-profile'
        exclude module: 'maven-project'
        exclude module: 'maven-settings'
        exclude module: 'nekohtml'
        exclude module: 'plexus-container-default'
        exclude module: 'plexus-interpolation'
        exclude module: 'plexus-utils'
        exclude module: 'wagon-file'
        exclude module: 'wagon-http-lightweight'
        exclude module: 'wagon-http-shared'
        exclude module: 'wagon-provider-api'
        exclude group: 'com.android.support', module: 'support-v4'
      }
    }
    

    上面的代码还包含https://code.google.com/p/android/issues/detail?id=69174的解决方法 .

    更多细节:http://chrisjenx.com/gradle-robolectric-jacoco-dagger/

  • -3

    我是_991665的解决方案,但是有一些小缺点,即在我们的项目中我们使用flavor并对这些flavor进行一些额外的测试以及每个的额外java代码 . 我们还使用不同的构建类型 . 因此,依赖于"testDebug"任务的解决方案还不够好 . 这是我的解决方案:在app模块中的build.gradle中添加

    apply from: '../app/jacoco.gradle'
    

    然后在app模块中创建一个jacoco.gradle文件,其中包含以下内容:

    apply plugin: 'jacoco'
    
        jacoco {
            toolVersion "0.7.1.201405082137"
        }
    
        def getFlavorFromVariant(String variantName) {
            def flavorString = variantName.replaceAll(/(.*)([A-Z].*)/) { all, flavorName, buildTypeName ->
               flavorName
            }
            return flavorString;
        }
    
        def getBuildTypeFromVariant(String variantName) {
            def buildTypeString = variantName.replaceAll(/(.*)([A-Z].*)/) { all, flavorName, buildTypeName ->
                "${buildTypeName.toLowerCase()}"
            }
            return buildTypeString;
        }
    
        def getFullTestTaskName(String variantName) {
            return "test${variantName.capitalize()}UnitTest";
        }
    
        android.applicationVariants.all { variant ->
            def variantName = variant.name;
            def flavorFromVariant = getFlavorFromVariant("${variantName}");
            def buildTypeFromVariant = getBuildTypeFromVariant("${variantName}");
            def testTaskName = getFullTestTaskName("${variantName}")
    
            task ("jacoco${variantName.capitalize()}TestReport", type: JacocoReport, dependsOn: testTaskName) {
                group = "Reporting"
                description = "Generate JaCoCo coverage reports after running tests for variant: ${variantName}."
                reports {
                    xml.enabled = true
                    html.enabled = true
                }
    
                classDirectories = fileTree(
                        dir: "./build/intermediates/classes/${flavorFromVariant}/${buildTypeFromVariant}",
                        excludes: ['**/R*.class',
                                   '**/*$InjectAdapter.class',
                                   '**/*$ModuleAdapter.class',
                                   '**/*$ViewInjector*.class'
                        ]
                )
    
                logger.info("Configuring JaCoCo for flavor: ${flavorFromVariant}, buildType: ${buildTypeFromVariant}, task: ${testTaskName}");
    
                def coverageSourceDirs = [
                        '../app/src/main/java',
                        "../app/src/${flavorFromVariant}/java"
                ]
                sourceDirectories = files(coverageSourceDirs)
                executionData = files("$buildDir/jacoco/${testTaskName}.exec")
                // Bit hacky but fixes https://code.google.com/p/android/issues/detail?id=69174.
                // We iterate through the compiled .class tree and rename $$ to $.
                doFirst {
                    new File("$buildDir/intermediates/classes/").eachFileRecurse { file ->
                        if (file.name.contains('$$')) {
                            file.renameTo(file.path.replace('$$', '$'))
                        }
                    }
                }
            }
        }
    

    您可以从命令行执行它,如下所示:

    .gradlew jacocoFlavor1DebugTestReport
    

    要么

    .gradlew jacocoOtherflavorPrereleaseTestReport
    

    在我们的项目中,我们使用一个约定,不要在flavor和build类型名称中使用大写字母,但如果你的项目不遵循这个约定,你只需更改getFlavorFromVariant(..)和getBuildTypeFromVariant(..)函数

    希望这有助于某人

  • 23

    您可以尝试使用此Gradle插件:https://github.com/arturdm/jacoco-android-gradle-plugin

    这里的答案还有一点https://stackoverflow.com/a/32572259/1711454 .

  • 6

    您是否尝试添加以下内容:

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

    然后而不是运行 ./gradlew jacocoTestReport 运行 ./gradlew test jacocoTestReport .

    如果一切顺利,您应该在 build/reports/jacoco/test/html/index.html 找到测试结果 .

相关问题