web-dev-qa-db-fra.com

Couverture du code de test Android avec le plugin JaCoCo Gradle

Je suis nouveau dans les tests Gradle et Android, mais j'ai déjà converti mon projet Android pour le construire avec Gradle.

J'essaie maintenant de réaliser une couverture de test d'un projet Android avec le plug-in JaCoCo de Gradle.

J'ai ajouté les éléments suivants à mon fichier build.gradle:

apply plugin: 'jacoco'

Et quand je lance "gradle jacocoTestReport" l'erreur suivante:

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

De la documentation, je suis censé appliquer également le plugin 'Java', mais cela est en conflit avec le plugin 'Android'.

Y a-t-il un moyen de contourner ceci?

Merci d'avance.

32
Henrique Rocha

Voici comment j'utilise 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'
  }
}

Le code ci-dessus contient également une solution de contournement pour https://code.google.com/p/Android/issues/detail?id=69174 .

Plus de détails: http://chrisjenx.com/gradle-robolectric-jacoco-dagger/

23
Hieu Rocker

J'utilise JaCoCo avec un projet utilisant RoboGuice, Butterknife et Robolectric. J'ai été capable de l'installer avec la solution de @Hieu Rocker, mais il y avait quelques inconvénients mineurs: dans notre projet, nous utilisons des versions et des tests supplémentaires pour ces versions ainsi que du code Java supplémentaire pour chacune d'entre elles. Nous utilisons également différents types de build. Par conséquent, une solution reposant sur la tâche "testDebug" n'était pas suffisante . Voici ma solution: Dans build.gradle in app module add

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

Créez ensuite un fichier jacoco.gradle à l'intérieur de app module avec le contenu suivant:


 applique le plugin: 'jacoco' 

 jacoco {
 toolVersion "0.7.1.201405082137" 
 } 

 def getFlavorFromVariant (String variantName) {
 def flavourString = variantName.replaceAll (/ (. *) ([A-Z]. *) /) {all ,avorName, buildTypeName -> 
 flavourName 
 } 
 renvoyer flavourString; 
 } 

 def getBuildTypeFromVariant (String variantName) {
 def buildTypeString = variantName.replaceAll (/ (. *) ([AZ]. *) /) {tout, Nom de saveur, Nom de type de construction -> 
 "$ {buildTypeName.toLowerCase ()}" 
 } 
 renvoyer buildTypeString; 
 } 

 def getFullTestTaskName (String variantName) {
 renvoie "test $ {variantName.capitalize ()} UnitTest"; 
 } 

 Android.applicationVariants.all {variante -> 
 def variantName = variant.name; 
 def flavourFromVariant = getFlavorFromVariant ("$ {variantName}"); 
 def buildTypeFromVariant = getBuildTypeFromVariant ("$ {variantName}"); 
 def testTaskName = getFullTestTaskName ("$ {variantName}") 

 task ("jacoco $ {variantName.capitalize ()} TestReport", tapez: JacocoReport, dependOn: testTaskName) {
 group = "Reporting" 
 description = "Générer des rapports de couverture JaCoCo après l'exécution de tests pour la variante: $ {variantName}." 
 rapports {
 xml.enabled = true 
 html.enabled = true 
 } 

 classDirectories = fileTree (
 dir: "./build/intermediates/classes/${flavorFromVariant}/${buildTypeFromVariantBuch" ,
 exclut: ['**/R * .class', 
 '*. */* $ InjectAdapter.class ', 
' **/* $ ModuleAdapter.class ', 
' **/* $ ViewInjector * .class '
] 
) 

 logger.info ("Configuration de JaCoCo pour la saveur: $ {flavourFromVariant}, buildType: $ {buildTypeFromVariant}, tâche: $ {testTaskName}" "); 

 def coverageSourceDirs = [
 '../app/src/main/Java' ,
 "../app/src/${flavorFromVariant}/Java"
 ] 
 sourceDirectories = fichiers (coverageSourceDirs) 
 executionData = fichiers ("$ buildDir/jacoco/$ {testTaskName} .exec") 
 // Bit hacky mais corrige https://code.google.com/p/Android/issues/detail?id=69174.
 // Nous parcourons l'arborescence .class compilée et renommons $$ en $ .
 faire en premier {
 nouveau fichier ("$ buildDir/intermediates/classes /"). eachFileRecurse {fichier -> 
 if (nom.fichier.contains ('$$')) {
 file.renameTo (file.path.replace ('$$', '$')) 
 } 
 } 
 } 
 } 
 } 

Vous pouvez l'exécuter en ligne de commande comme ceci:

.gradlew jacocoFlavor1DebugTestReport

ou

.gradlew jacocoOtherflavorPrereleaseTestReport

Dans notre projet, nous utilisons une convention pour ne pas utiliser de majuscule dans les noms de type et de construction, mais si votre projet ne respecte pas cette convention, vous pouvez simplement changer getFlavorFromVariant (..) et getBuildTypeFromVariant (..) les fonctions

J'espère que cela aide quelqu'un

6
Piotr Zawadzki

Vous pouvez essayer d’utiliser ce plugin Gradle: https://github.com/arturdm/jacoco-Android-gradle-plugin

Il y a un peu plus dans la réponse ici https://stackoverflow.com/a/32572259/1711454 .

0
Artur Stepniewski