How to aggregate test reports in android multi-module gradle project in 2019
Asked Answered
D

1

7

I have a multi-module Android gradle project.

project
  |- app
  |- module1
  |- module2

Each of the modules contains unit tests, the app module also contains Instrumented Tests. Instead of taking the xml reports from the modules I would like to store them in one place, e.g. /build/tests/reports.

What I tried so far to achieve this is to set the report dir to this path

android {
    testOptions {
        resultsDir "$rootDir/build/test/results"
        reportDir "$rootDir/build/test/reports"
    }
}

I applied this in all the module's gradle files. But it seems as if this only works for the instrumented / connected test reports. How can I also achieve this for unit tests?

Deepset answered 11/7, 2019 at 7:12 Comment(2)
You want it all test reports into one file or all test reports as different file but in one directory? In second case you can use copyTask. https://mcmap.net/q/1628481/-how-do-i-get-file-outputs-of-gradle-taskArturoartus
One directory - ok, thanks for the tipDeepset
S
1

NEW ANSWER USING THIRD PARTY GRADLE PLUGIN: I actually manage to fix the issue of duplicate execution of test using this solution

In your build.gradle project level, add the below code.

plugins {
    base
    id("io.github.gmazzo.test.aggregation.coverage") version "2.2.0" // optional
    id("io.github.gmazzo.test.aggregation.results") version "2.2.0"
}

// optional
testAggregation {
    modules { // add your target module here
        include(project(":app:"), project(":app:libs:module1"), project(":app:libs:module2"))
        exclude(rootProject)
    }
    coverage {
        exclude( // Lets you exclude some part of the code on coverage report 
            // Android
            "**/R.class",
            "**/R$*.class",
            "**/BuildConfig.*",
            "**/Manifest*.*",
            "**/*Test*.*",
            "android/**/*.*",
            // DataBinding/ViewBinding
            "android/databinding/**/*.class",
            "**/android/databinding/*Binding.class",
            "**/android/databinding/*",
            "**/androidx/databinding/*",
            "**/BR.*",
            "**/databinding/*Binding.class",
            // Dagger
            "**/*_MembersInjector.class",
            "**/Dagger*Component.class",
            "**/Dagger*Component${'$'}Builder.class",
            "**/Dagger*Subcomponent*.class",
            "**/*Subcomponent${'$'}Builder.class",
            "**/*Module_*Factory.class",
            "**/di/module/*",
            "**/*_Factory*.*",
            "**/*Module*.*",
            "**/*Dagger*.*",
            "**/*Hilt*.*",
            // Kotlin
            "**/*MapperImpl*.*",
            "**/*${'$'}ViewInjector*.*",
            "**/*${'$'}ViewBinder*.*",
            "**/*Component*.*",
            "**/*${'$'}Lambda$*.*",
            "**/*Companion*.*",
            "**/*MembersInjector*.*",
            "**/*_Provide*Factory*.*",
            "**/*Extensions*.*",
            // Sealed and data classes
            "**/*${'$'}Result.*",
            "**/*${'$'}Result$*.*",
            // Adapters generated by moshi
            "**/*JsonAdapter.*",
        )
    }
}

// optional
tasks.check {
    dependsOn(tasks.jacocoAggregatedCoverageVerification)
}

Then add the following on each module level build.gradle

buildTypes {
        debug {
            enableUnitTestCoverage = true 
        }
        release {
            aggregateTestCoverage = false // This prevents duplication of unit test result
        }
}

Then run ./gradlew jacocoAggregatedReport for code coverage report (if plugin is added) or ./gradlew testAggregatedReport for unit test report

OLD ANSWER

Groovy

task testReport(type: TestReport) {
  destinationDir = file("$buildDir/reports/allTests")
  // Combine all 'test' task results into a single HTML report
  reportOn subprojects.collect { it.tasks.withType(Test) }
}

Kotlin DSL (Tested)

tasks.register<TestReport>("testReport") {
destinationDirectory.set(file("$rootDir/reports/tests/unitTest"))
// Combine all 'test' task results into a single HTML report
testResults.from(subprojects.flatMap { it.tasks.withType(Test::class) })
}

Then execute

./gradlew testReport

Note: Add this in the project level build.gradle not in the module level, however if you wanted it in app level then use allprojects instead of subprojects. Unfortunately the tests are being duplicated, I don't have any solution as of the moment. My guess is due to both release and debug test being run, feel free to improve my answer.

Soriano answered 3/4 at 21:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.