2013-08-21 12 views
32

私はGradleとAndroidのテストを初めて行っていますが、すでにGradleを使用してAndroidプロジェクトを変換しました。JaCoCo GradleプラグインによるAndroidテストコードカバレッジ

今、GradleのJaCoCoプラグインを使用してAndroidプロジェクトのテストカバレッジを実行しようとしています。

apply plugin: 'jacoco' 

を私は "GradleのjacocoTestReport" 次のエラーを実行するとき:ドキュメントから

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

を私はなってる

私は私のbuild.gradleファイルに以下を追加しましたプラグイン 'java'も適用しますが、プラグイン 'android'と衝突します。

方法はありますか?

ありがとうございます。

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

そして代わりに./gradlew jacocoTestReport実行./gradlew test jacocoTestReportを実行しているの:

+0

テストカバレッジは、AndroidのGradleプラグインではまだサポートされていません。私も達成するための方法を探していますが、アンドロイドのためのグラデル・プラグインがアンドロイドにカバレッジを生成するよう指示していないので、今は絶望的です。 – Snicolas

+0

javaプラグインとandroidプラグインが互換性があるまでは、ant.javaを使用してテストを実行し、カバレッジレポートを作成することもできます。基本的にあなたがANTでやることをやってください。 – skipy

+2

@skipy:これを蟻で行う方法の例がありますか?私は、 'jacocoagent'の設定とエミュレータからのレポートの取得の例を見つけることができませんでした。 – unholysampler

答えて

22

は私が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' 
    } 
} 

上記のコードはまたhttps://code.google.com/p/android/issues/detail?id=69174の回避策が含まれています。

詳細:http://chrisjenx.com/gradle-robolectric-jacoco-dagger/

+0

上記のスクリプトをAndroidプラグインとどのように統合しましたか?あなたは私にあなたのgradleファイルを見るためのリンクを教えてもらえますか? – Borys

+0

@Borysはrobolectricを統合した 'build.gradle'をすでに所有していると仮定しています。 'apply plugin'セクションに' apply plugin: 'jacoco'を入れて、残りの部分を 'build.gradle'の最後に置きます。 './gradlew testDebug jacocoTestReport'を実行することができます。それでおしまい。 –

+0

Hm ....次のエラーが表示されます。「タスクの依存関係を判別できませんでした:app:jacocoTestReport」 – Borys

-3

では、次を追加してみてくださいでした。

すべてがうまくいく場合は、テスト結果はbuild/reports/jacoco/test/html/index.htmlであるはずです。ここで

+1

はあなたのソリューションを試してみましたが、ここで私が得るものです: >メソッドjacocoTestReportを見つけることができませんでした()の引数に[build_5dkpq0odkgno9tsiihqqr1k86u $ _run_closure4 @ 49c96202]プロジェクトに「:アプリケーション」。 – Egor

+1

jacocoプラグインはアンドロイドプラグインと互換性がありません。 jacocoプラグインにはJavaプロジェクトが必要です。 – skyisle

+0

それで、どのようにAndroidプロジェクトでそれを実行するには? – Borys

6

私はRoboGuice、ButterknifeとRobolectricを使用してプロジェクトをJaCoCoを使用しています。私は@Hieu Rockerのソリューションを使って設定することができましたが、いくつかのマイナーな欠点がありました。私たちのプロジェクトでは、フレーバーを使用し、それらのフレーバーの追加テストとそれぞれのJavaコードを追加しました。また、異なるビルドタイプも使用しています。したがって、 "testDebug"タスクに依存する解決策は十分ではありませんでした。

 

    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('$$', '$')) 
        } 
       } 
      } 
     } 
    } 
:モジュールはその後 アプリ以下の内容でモジュールの内部 jacoco.gradleファイルを作成
apply from: '../app/jacoco.gradle' 

を追加 build.gradle アプリで: はここに私のソリューションです

コマンドラインから次のように実行できます。

私たちのプロジェクトで
.gradlew jacocoFlavor1DebugTestReport 

または

.gradlew jacocoOtherflavorPrereleaseTestReport 

我々は味の内側に大文字を使用し、タイプ名を作成しないように規則を使用しますが、あなたのプロジェクトは、この規則に従わない場合は、単にgetFlavorFromVariantを(変更することができます。 。)getBuildTypeFromVariant(..)機能

これはあなたがこのGradleのプラグインを使用しようとすることができ、誰か

+4

こんにちはPiotr、Imを得る タスク ':app:jacocoDebugTestReport'の依存関係を特定できませんでした。 > 'testDebug'パスのタスクが ':app'プロジェクトに見つかりませんでした。どんな考え? – AndroidGecko

+0

@AndroidGecko私は答えを更新しました。テストタスク名の末尾に「UnitTest」が追加されました。それが役に立てば幸い! –

関連する問題