2016-03-01 24 views
16

Chciałem generować raporty dotyczące pokrycia kodu na moich testach JUnit w moim projekcie Android, więc dodałem wtyczkę JaCoCo gradle. To jest mój poziom projekt build.gradle file:JaCoCo nie działa z testami Robolectric

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() }) 
    } 
} 

Działa świetnie, uruchamiając ./gradlew jacocoFullReport. Ale niestety zakres nie jest zgłaszany dla testów, które są uruchamiane z RobolectricTestRunner (instrukcje, które są oczywiście wywoływane w testach, nie są zgłaszane jako zakryte). Testy bez adnotacji i uruchamiania z raportem są w porządku.

Każda pomoc będzie doceniana w celu rozwiązania tego problemu.

Aktualizacja 1: Zauważyłem, że powinienem używać RobolectricGradleTestRunner. Ale to nie pomogło.

+0

Chcę powiedzieć, że jest to zdecydowanie możliwe, ale nie mam pojęcia, jak to naprawić. Udało mi się uzyskać zasięg kodu pracujący dla Robolectric na starej posadzie, ale to było rok temu i już nie mam już dostępu do tego kodu. Przepraszam, że nie mogę pomóc! –

+0

'testCoverageEnabled' w późniejszych wersjach gradle używa Jacoco, nie musisz stosować wtyczki. Spróbuj bez wtyczki. –

+0

@NikolaDespotoski Uważam, że ustawienie testCoverageEnabled na true działa tylko z testami oprzyrządowania Android, które wymagają podłączonego urządzenia. I tego staram się unikać, używając Robolectric. – Longi

Odpowiedz

14

To jest znany problem z ewentualnego obejścia - https://github.com/jacoco/jacoco/pull/288

Albo downgrade jacoco wersję do 0.7.1.201405082137

UPDATE

Rozwiązaniem nie jest już potrzebny. Musisz użyć gradle wersja 2.13 i jacoco wersja 0.7.6.201602180812.

Root Update build.gradle:

buildscript { 
    dependencies { 
     classpath 'org.jacoco:org.jacoco.core:0.7.6.201602180812' 
    } 
} 

task wrapper(type: Wrapper) { 
    gradleVersion = '2.13' 
} 

Run ./gradlew wrapper

projekt Aktualizacja build.gradle:

apply plugin: 'jacoco' 

android { 
    testOptions { 
    unitTests.all { 
     jacoco { 
     includeNoLocationClasses = true 
     } 
    } 
    } 
} 
+1

Niestety, obejście problemu nie działa dla mnie. – Longi

+0

W tym przypadku, jeśli to nie jest główny dla ciebie, wówczas niższa wersja jacoco do '0.7.1.201405082137'. Wciąż może to być problem, jeśli używasz najnowszej wtyczki jacoko firmy Jenkins. Również wersja downgrade to coś '1.8' –

+0

Downgrading jacoco załatwił sprawę. Używam travis-ci i nie ma z tym problemu. – Longi

1

miałem ten sam problem. Zmieniłem wersję wtyczki jacoco i dodałem opcję includenolocationclasses. Oto działający plik jacoco.gradle (używam wtyczki zbiorczej 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 
       } 
      } 
     } 
    } 
} 
Powiązane problemy