android code-coverage robolectric jacoco

android - JaCoCo no funciona con pruebas Robolectric



code-coverage (5)

Quería generar informes de cobertura de código en mis pruebas JUnit en mi proyecto de Android, así que agregué el plugin JaCoCo gradle. Este es mi archivo build.gradle nivel de proyecto:

apply plugin: ''jacoco'' buildscript { repositories { jcenter() } dependencies { classpath ''com.android.tools.build:gradle:2.0.0-beta6'' classpath ''com.neenbedankt.gradle.plugins:android-apt:1.8'' } } allprojects { repositories { jcenter() maven { url "https://oss.sonatype.org/content/repositories/snapshots" } } } task clean(type: Delete) { delete rootProject.buildDir } subprojects { prj -> apply plugin: ''jacoco'' jacoco { toolVersion ''0.7.6.201602180812'' } task jacocoReport(type: JacocoReport, dependsOn: ''testDebugUnitTest'') { group = ''Reporting'' description = ''Generate Jacoco coverage reports after running tests.'' reports { xml { enabled = true destination "${prj.buildDir}/reports/jacoco/jacoco.xml" } html { enabled = true destination "${prj.buildDir}/reports/jacoco" } } classDirectories = fileTree( dir: ''build/intermediates/classes/debug'', excludes: [ ''**/R*.class'', ''**/BuildConfig*'', ''**/*$$*'' ] ) sourceDirectories = files(''src/main/java'') executionData = files(''build/jacoco/testDebugUnitTest.exec'') doFirst { files(''build/intermediates/classes/debug'').getFiles().each { file -> if (file.name.contains(''$$'')) { file.renameTo(file.path.replace(''$$'', ''$'')) } } } } } jacoco { toolVersion ''0.7.6.201602180812'' } task jacocoFullReport(type: JacocoReport, group: ''Coverage reports'') { group = ''Reporting'' description = ''Generates an aggregate report from all subprojects'' //noinspection GrUnresolvedAccess dependsOn(subprojects.jacocoReport) additionalSourceDirs = project.files(subprojects.jacocoReport.sourceDirectories) sourceDirectories = project.files(subprojects.jacocoReport.sourceDirectories) classDirectories = project.files(subprojects.jacocoReport.classDirectories) executionData = project.files(subprojects.jacocoReport.executionData) reports { xml { enabled = true destination "${buildDir}/reports/jacoco/full/jacoco.xml" } html { enabled = true destination "${buildDir}/reports/jacoco/full" } } doFirst { //noinspection GroovyAssignabilityCheck executionData = files(executionData.findAll { it.exists() }) } }

Funciona muy bien ejecutando ./gradlew jacocoFullReport . Pero, desafortunadamente, no se informa la cobertura de las pruebas que se ejecutan con RobolectricTestRunner (las instrucciones que obviamente se mencionan en las pruebas no se informan como cubiertas). Las pruebas sin la anotación @RunWith o ejecutadas con MockitoJUnitTestRunner informan que la cobertura está bien.

Cualquier ayuda sería apreciada para solucionar este problema.

Actualización 1: noté que debería estar usando RobolectricGradleTestRunner . Pero no ayudó.


Cambie el corredor de cobertura a Jacoco en Android Studio 1- Seleccione la aplicación (raíz del proyecto) 2 Haga clic en el menú (Ejecutar -> Editar configuraciones -> Código de cobertura -> Elija JaCoCo).


La respuesta aceptada es un poco anticuada. Aquí hay una solución similar que acabamos de implementar. En el módulo (es decir, la aplicación) build.gradle agregar:

apply plugin: ''jacoco'' tasks.withType(Test) { jacoco.includeNoLocationClasses = true }

Esto requiere JaCoCo 7.6+, pero es probable que ya lo estés usando.

Notas para el estudio:

  1. Esto solo corrige el CLI. Si ejecuta la cobertura de Studio utilizando JaCoCo, la cobertura de Robolectric aún no se informa. El IntelliJ Coverage Runner por defecto parece funcionar bien.
  2. La prueba se bloqueaba de forma intermitente en Studio a menos que agregue -noverificar a Android JUnit -> Opciones de VM


Se sabe que existe un problema con la posible solución alternativa: https://github.com/jacoco/jacoco/pull/288

O bajar la versión 0.7.1.201405082137 a 0.7.1.201405082137

ACTUALIZAR

La solución ya no es necesaria. Debe usar la versión gradle 2.13 y la versión 0.7.6.201602180812 .

Actualizar root build.gradle :

buildscript { dependencies { classpath ''org.jacoco:org.jacoco.core:0.7.6.201602180812'' } } task wrapper( type: Wrapper ) { gradleVersion = ''2.13'' }

Ejecutar ./gradlew wrapper

Actualizar proyecto build.gradle :

apply plugin: ''jacoco'' android { testOptions { unitTests.all { jacoco { includeNoLocationClasses = true } } } }


Tuve el mismo problema. Cambié la versión del complemento jacoco y agregué la propiedad includeenolocationclasses. Aquí está el archivo jacoco.gradle en funcionamiento (estoy usando Gradle Wrap 2.14.1):

apply plugin: ''jacoco'' jacoco { toolVersion = "0.7.6.201602180812" } android { testOptions { unitTests.all { jacoco { includeNoLocationClasses = true } } } } project.afterEvaluate { // Grab all build types and product flavors def buildTypes = android.buildTypes.collect { type -> type.name } def productFlavors = android.productFlavors.collect { flavor -> flavor.name } println(buildTypes) println(productFlavors) // When no product flavors defined, use empty if (!productFlavors) productFlavors.add('''') productFlavors.each { productFlavorName -> buildTypes.each { buildTypeName -> def sourceName, sourcePath if (!productFlavorName) { sourceName = sourcePath = "${buildTypeName}" } else { sourceName = "${productFlavorName}${buildTypeName.capitalize()}" sourcePath = "${productFlavorName}/${buildTypeName}" } def testTaskName = "test${sourceName.capitalize()}UnitTest" println("SourceName:${sourceName}") println("SourcePath:${sourcePath}") println("testTaskName:${testTaskName}") // Create coverage task of form ''testFlavorTypeCoverage'' depending on ''testFlavorTypeUnitTest'' task "${testTaskName}Coverage" (type:JacocoReport, dependsOn: "$testTaskName") { group = "Reporting" description = "Generate Jacoco coverage reports on the ${sourceName.capitalize()} build." classDirectories = fileTree( dir: "${project.buildDir}/intermediates/classes/${sourcePath}", excludes: [''**/R.class'', ''**/R$*.class'', ''**/*$ViewInjector*.*'', ''**/*$ViewBinder*.*'', ''**/BuildConfig.*'', ''**/Manifest*.*''] ) def coverageSourceDirs = [ "src/main/java", "src/$productFlavorName/java", "src/$buildTypeName/java" ] additionalSourceDirs = files(coverageSourceDirs) sourceDirectories = files(coverageSourceDirs) executionData = files("${project.buildDir}/jacoco/${testTaskName}.exec") println("${project.buildDir}/jacoco/${testTaskName}.exec") reports { xml.enabled = true html.enabled = true } } } } }