Jacoco和unit testing使用android-gradle-plugin代码覆盖> = 1.1

我最近开始在我的一个项目中集成android-gradle-plugin 1.1.0。 该项目使用robolectric 2.4来运行unit testing。

这是一个具有非常复杂的依赖关系的多模块项目(一些模块依赖于其他模块)。 类似的东西:

 --> application-module (dependsOn: module1, module2, module-core) --> module1 (dependsOn: module-core) --> module2 (dependsOn: module-core) --> module-core (dependsOn: module3, module4) --> module3 (library dependencies) --> module4 (library dependencies) 

要获得更清晰的图片,请参阅jacoco示例项目。

我试图整合JaCoCo为unit testing生成报告,但在我看来,它只运行基本上是仪器testing的androidTests

在Google之后,我遇到了GitHub和其他文章中的一些项目,但是他们主要关注的是以前版本的android-gradle-plugin或者正在使用其他第三方插件,比如android-unit-test

可能是我失去了我的能力谷歌。 但有人可以指向我的方向,我可以find一些关于在Android的gradle插件的新东西的文件,以及如何运行的unit testingjacoco任务?

UPDATE

通过nenick的例子的脚本:

 apply plugin: "jacoco" configurations { jacocoReport } task jacocoReport(dependsOn: 'testDebug') << { ant { taskdef(name:'jacocoreport', classname: 'org.jacoco.ant.ReportTask', classpath: configurations.jacocoReport.asPath) mkdir dir: "${buildDir}/test-coverage-report" mkdir dir: "${buildDir}/reports/jacoco/test/" jacocoreport { executiondata = files("${buildDir}/jacoco/testDebug.exec") structure(name: "${rootProject.name}") { classfiles { fileset (dir: "${buildDir}/intermediates/classes/debug") { //exclude(name: '**/*_*.class') exclude(name: '**/R.class') exclude(name: '**/R$*.class') exclude(name: '**/BuildConfig.class') } } sourcefiles { fileset dir: "src/main/java" fileset dir: "${buildDir}/generated/source/buildConfig/debug" fileset dir: "${buildDir}/generated/source/r/debug" } } xml destfile: "${buildDir}/reports/jacoco/test/jacocoTestReport.xml" html destdir: "${buildDir}/test-coverage-report/" } } } dependencies { jacocoReport 'org.jacoco:org.jacoco.ant:0.7.2.201409121644' } 

之后,./ ./gradlew jacocoReport执行并生成报告,但显示0(零)testing覆盖率,这是不可能的,因为至less有一半的类都被testing过了。

UPDATE_2

试过这个例子 。 将下一个任务添加到我的一个gradle构build文件中:

 task jacocoTestReport(type:JacocoReport, dependsOn: "testDebug") { group = "Reporting" description = "Generate Jacoco coverage reports" classDirectories = fileTree( dir: "${buildDir}/intermediates/classes/debug", excludes: ['**/R.class', '**/R$*.class', '**/*$ViewInjector*.*', '**/BuildConfig.*', '**/Manifest*.*'] ) sourceDirectories = files("${buildDir.parent}/src/main/java") additionalSourceDirs = files([ "${buildDir}/generated/source/buildConfig/debug", "${buildDir}/generated/source/r/debug" ]) executionData = files("${buildDir}/jacoco/testDebug.exec") reports { xml.enabled = true html.enabled = true } } 

同样的问题,报告生成,但代码覆盖率仍然是零。

UPDATE_3

它接缝来自UPDATE_2的任务工作,但仅适用于具有apply plugin: 'com.android.application'的模块apply plugin: 'com.android.application' (正确生成的报告)。 但对于Android库( apply plugin: 'com.android.library' )的模块,报告显示零覆盖率,尽pipe模块包含更多的testing,然后是应用程序模块。

UPDATE_4

创build了一个简单的示例项目来演示我的问题。 目前,如果运行./gradlew jacocoReport ,则会生成报告,但是没有为模块项目显示testing覆盖率。 看到这个链接

简短说明:当testing是AndroidUnitTests(JUnit 4和Robolectric白板)JaCoCo报告显示所有模块的覆盖范围。

有任何想法吗?

在麻烦之后,我决定为此创build一个开源的Gradle插件 。

根build.gradle

 buildscript { repositories { mavenCentral() // optional if you have this one already } dependencies { classpath 'com.vanniktech:gradle-android-junit-jacoco-plugin:0.8.0' } } apply plugin: 'com.vanniktech.android.junit.jacoco' 

然后简单地执行

 ./gradlew jacocoTestReportDebug 

它将以debugging模式运行JUnittesting,然后在相应的build目录中为您提供xml和html格式的Jacoco输出。

它也支持口味。 有两种口味的红色和蓝色这些任务将被创build

  • jacocoTestReportRedDebug
  • jacocoTestReportBlueDebug
  • jacocoTestReportRedRelease
  • jacocoTestReportBlueRelease

经过一些额外的search后,我偶然发现这个项目,我不得不做一些修改,以便解决scheme可以为我的types的项目工作,但现在testing覆盖率报告生成正确。

我已经将所采用的修改推到我的github示例库中,以防将来出现类似的问题。

我使用这个博客文章设置我的unit testinggradle 1.2。 然后,我将这里和其他地方find的信息拼凑在一起,将代码覆盖范围添加到独立模块,而不是整个项目。 在我的库模块build.gradle文件中,我添加了以下内容:

 apply plugin: 'jacoco' def jacocoExcludes = [ 'com/mylibrary/excludedpackage/**' ] android { ... } android.libraryVariants.all { variant -> task("test${variant.name.capitalize()}WithCoverage", type: JacocoReport, dependsOn: "test${variant.name.capitalize()}") { group = 'verification' description = "Run unit test for the ${variant.name} build with Jacoco code coverage reports." classDirectories = fileTree( dir: variant.javaCompile.destinationDir, excludes: rootProject.ext.jacocoExcludes.plus(jacocoExcludes) ) sourceDirectories = files(variant.javaCompile.source) executionData = files("${buildDir}/jacoco/test${variant.name.capitalize()}.exec") reports { xml.enabled true xml.destination "${buildDir}/reports/jacoco/${variant.name}/${variant.name}.xml" html.destination "${buildDir}/reports/jacoco/${variant.name}/html" } } } 

在我的项目build.gradle文件中,我添加了通用排除项:

 ext.jacocoExcludes = [ 'android/**', '**/*$$*', '**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Service.*' ] 

此外,它看起来像unit testing的代码覆盖面可能会在未来的问题144664内置

警告:这是一个黑客! 使用上面的configuration,我根据select的构build任务,将一个hack切换到应用程序和库之间的android插件。 这对我来说很好,因为我最终没有提交应用程序模式的代码。

 // dynamically change the android plugin to application if we are running unit tests or test reports. project.ext.androidPlugin = 'com.android.library' for (String taskName : project.gradle.startParameter.taskNames) { if (taskName.contains('UnitTest') || taskName.contains('jacocoTestReport')) { project.ext.androidPlugin = 'com.android.application' break } } logger.lifecycle("Setting android pluging to ${project.ext.androidPlugin}") apply plugin: project.ext.androidPlugin ... apply plugin: 'jacoco' configurations { jacocoReport } task jacocoTestReport(type:JacocoReport, dependsOn: "testDebug") { group = "Reporting" description = "Generate Jacoco coverage reports" classDirectories = fileTree( dir: "${buildDir}/intermediates/classes/debug", excludes: ['**/R.class', '**/R$*.class', '**/*$ViewInjector*.*', '**/BuildConfig.*', '**/Manifest*.*'] ) sourceDirectories = files("${buildDir.parent}/src/main/java") additionalSourceDirs = files([ "${buildDir}/generated/source/buildConfig/debug", "${buildDir}/generated/source/r/debug" ]) executionData = files("${buildDir}/jacoco/testDebug.exec") reports { xml.enabled = true html.enabled = true } } 

让我们希望android工具团队尽快修复这个问题。

我终于可以看到我的代码覆盖了Android Studio 1.1的JUnittesting。

jacoco.gradle

 apply plugin: 'jacoco' jacoco { toolVersion "0.7.1.201405082137" } def coverageSourceDirs = [ "$projectDir/src/main/java", ] task jacocoTestReport(type: JacocoReport, dependsOn: "testDebug") { 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('$$', '$')) } } } } 

然后在模块的build.gradle文件(我把它放在androiddependencies之间):

 apply from: '../jacoco.gradle' 

也在androiddefaultConfig块中。 我已经添加了这个(不知道是否有必要,但是我从这个博客里得到了这个):

 android { defaultConfig { testHandleProfiling true testFunctionalTest true } } 

请享用。

我解决了JaCoCo的问题,并使其与最新的gradle android插件1.1.3一起工作

使用最新的gradle脚本进行项目: https : //github.com/OleksandrKucherenko / meter

参考文献:

如何在Android Studiounit testing中附加自己的实现而不是Mocks? https://plus.google.com/117981280628062796190/posts/8jWV22mnqUB

对于那些试图在Android版本中使用JaCoCo覆盖的人的小提示…意外的发现! https://plus.google.com/117981280628062796190/posts/RreU44qmeuP

JaCoCounit testing的XML / HTML报告 https://plus.google.com/u/0/+OleksandrKucherenko/posts/6vNWkkLed3b

我正面临与你一样的问题。 今天我完全删除了android studio,android sdk,gradle。 然后重新安装一切。 之后,我只是在应用程序build.gradle内添加。

debugging{testCoverageEnabled true}然后我运行./gradlew connectedChec。 一切都很完美。 Android工作室默认Jacoco为我工作的很好。 我认为也可以创build一个jacocoTestReport任务,然后创build代码coverage.I不知道为什么gradle和android studio以前不工作。

你可以尝试使用这个Gradle插件: https : //github.com/arturdm/jacoco-android-gradle-plugin

基本上,你需要做的就是像这样应用它:

 buildscript { repositories { jcenter() } dependencies { classpath 'com.dicedmelon.gradle:jacoco-android:0.1.1' } } apply plugin: 'com.android.library' // or 'com.android.application' apply plugin: 'jacoco-android' 

因此,您应该为每个变体获取JacocoReport任务。 运行下面的命令为它们生成代码覆盖率报告。

 $ ./gradlew jacocoTestReport 

请创build一个例子,我可以看看。 我想这是一些丢失的pathconfiguration。

  • 包括所有覆盖文件(* .exec)
  • 添加所有源path(module / src / main / java)
  • 添加所有的类path(模块/构build/中间体/类/debugging)

这里有两个例子可以看看