android testing gradle code-coverage jacoco

Cobertura del código de prueba de Android con el plugin JaCoCo Gradle



testing code-coverage (4)

¿Intentó agregar lo siguiente?

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

Y luego, en lugar de ejecutar ./gradlew jacocoTestReport ejecutar ./gradlew test jacocoTestReport .

Si todo va bien, debe encontrar los resultados de la prueba en build/reports/jacoco/test/html/index.html .

Soy nuevo en las pruebas de Gradle y Android, pero ya he convertido mi proyecto de Android para compilar con Gradle.

Ahora estoy intentando realizar una cobertura de prueba de un proyecto de Android con el complemento JaCoCo de Gradle.

He agregado lo siguiente a mi archivo build.gradle:

apply plugin: ''jacoco''

Y cuando ejecuto "gradle jacocoTestReport" aparece el siguiente error:

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

De la documentación se supone que también debo aplicar el plugin ''java'', pero entra en conflicto con el plugin ''android''.

¿Hay alguna forma de evitar esto?

Gracias por adelantado.


Así es como estoy usando 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'' } }

El código anterior también contiene una solución para https://code.google.com/p/android/issues/detail?id=69174 .

Más detalles: http://chrisjenx.com/gradle-robolectric-jacoco-dagger/


Estoy usando JaCoCo con un proyecto que usa RoboGuice, Butterknife y Robolectric. Pude configurarlo utilizando la solución de @Hieu Rocker, sin embargo, hubo algunos inconvenientes menores, es decir, en nuestro proyecto usamos sabores y tenemos algunas pruebas adicionales para esos sabores, así como código extra de Java para cada uno de ellos. También utilizamos diferentes tipos de compilación. Por lo tanto, una solución para confiar en la tarea "testDebug" no era lo suficientemente buena. Aquí está mi solución: en el módulo build.gradle in app add

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

Luego crea un archivo jacoco.gradle dentro del módulo de la aplicación con el siguiente contenido:

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(''$$'', ''$'')) } } } } }

Puede ejecutarlo desde línea de comandos de esta manera:

.gradlew jacocoFlavor1DebugTestReport

o

.gradlew jacocoOtherflavorPrereleaseTestReport

En nuestro proyecto utilizamos una convención para no utilizar letras mayúsculas dentro de los nombres de tipo de compilación y sabor, pero si su proyecto no sigue esta convención, simplemente puede cambiar las funciones getFlavorFromVariant (..) y getBuildTypeFromVariant (..)

Espero que esto ayude a alguien