2016-03-01 7 views
16

Я хотел генерировать отчеты о покрытии кода на своих тестах JUnit в моем проекте Android, поэтому я добавил плагин JaCoCo gradle. Это мой уровень проекта build.gradle файл:JaCoCo не работает с Robolectric test

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

Он отлично работает, запустив ./gradlew jacocoFullReport. Но, к сожалению, охват не сообщается для тестов, которые запускаются с RobolectricTestRunner (инструкции, которые, очевидно, вызывают в тестах, не сообщаются как покрытые). Тесты без @RunWith аннотации или запустите с MockitoJUnitTestRunner отчетный отчет просто отлично.

Любая помощь была бы оценена, чтобы исправить эту проблему.

Обновление 1: Я заметил, что должен использовать RobolectricGradleTestRunner. Но это не помогло.

+0

Я хочу сказать, что это, безусловно, возможно, но я понятия не имею, как это исправить. Мне удалось получить покрытие кода, работающее на Robolectric на старой работе, но это было год назад, и у меня больше нет доступа к этому коду. Извините, я не могу больше помочь! –

+0

'testCoverageEnabled' в более поздних версиях gradle использует Jacoco, вам не нужно применять плагин. Попробуйте без плагина. –

+0

@NikolaDespotoski Я считаю, что установка testCoverageEnabled to true работает только с андроидными инструментальными тестами, для которых требуется подключенное устройство. И этого я пытаюсь избежать, используя Robolectric. – Longi

ответ

14

Известно вопрос с возможным обходным путем - https://github.com/jacoco/jacoco/pull/288

Или понижает jacoco версии 0.7.1.201405082137

UPDATE

Обходной больше не требуется. Вы должны использовать gradle версия 2.13 и jacoco версия 0.7.6.201602180812.

корень 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

Обновление проекта build.gradle:

apply plugin: 'jacoco' 

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

К сожалению, обходной путь, похоже, не работает для меня. – Longi

+0

В этом случае, если это не принципиальная для вас, тогда нижняя версия jacoco равна '0.7.1.201405082137'. Это все еще может быть проблемой, если вы используете последний jacoco-модуль jenkins. Также понизить версию его до чего-то '1,8' –

+0

Ускоренный jacoco сделал трюк. Я использую travis-ci, и с этим нет никаких проблем. – Longi

3

Я столкнулась с такой же вопрос, но теперь она решена для меня по этой ссылке,

выпуск ссылка: https://github.com/robolectric/robolectric/issues/2230

Решение этой проблемы упоминается здесь:

https://github.com/dampcake/Robolectric-JaCoCo-Sample/commit/f9884b96ba5e456cddb3d4d2df277065bb26f1d3

+0

Евгений Мартынов предложил то же самое. Но это не сработало для меня. – Longi

1

Я была такая же проблема. Я изменил версию плагина jacoco и добавил свойство includesenolocationclasses. Здесь работает jacoco.gradle файл (я использую Gradle обертку 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 
       } 
      } 
     } 
    } 
} 
Смежные вопросы