Исключить из освещения многомодульного проекта с использованием jacoco и gradle - PullRequest
0 голосов
/ 14 апреля 2020

Я пытался исключить определенные классы и / или пакеты из отчета о покрытии, сгенерированного jacoco . Я работал с jacoco раньше, но это не был многомодульный проект, поэтому я попытался перевести конфигурацию и экспортировать ее в модули, но пока отчет возвращается полностью, игнорируя мой путь исключения.

Я испробовал множество решений, таких как:

Я не знаю, что я делаю неправильно, я не очень хорошо разбираюсь в gradle, и почти каждая найденная документация / пример использует проект с одним модулем , Я создал небольшой проект и нажал gitlab , чтобы вы могли выглядеть лучше.

Желаемый результат - возможность добавлять дополнительные пути или классы в модули напрямую.

Я был бы очень признателен за любую помощь, которую вы можете оказать.


Фрагменты кода:

Root build.gradle.kts

plugins {
    kotlin("jvm") version "1.3.71"
    jacoco
}

repositories {
    mavenCentral()
}

defaultTasks("clean", "build", "test")

allprojects {
    apply(plugin = "org.jetbrains.kotlin.jvm")
    apply(plugin = "jacoco")

    group = "org.example"
    version = "1.0-SNAPSHOT"

    repositories {
        mavenCentral()
    }

    jacoco {
        toolVersion = "0.8.5"
    }

    dependencies {
        implementation(kotlin("stdlib-jdk8"))
        testImplementation("org.testng:testng:6.14.3")
    }

    configure<JavaPluginConvention> {
        sourceCompatibility = JavaVersion.VERSION_1_8
    }

    tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile::class) {
        kotlinOptions {
            jvmTarget = "1.8"
        }
    }

    tasks.test {
        useTestNG()
        finalizedBy("jacocoTestReport")
    }
}

tasks.jacocoTestReport {
    val sourceDirs = sourceSets.main.get().allSource.srcDirs
    additionalSourceDirs.setFrom(sourceDirs)
    sourceDirectories.setFrom(sourceDirs)
    classDirectories.setFrom(sourceSets.main.get().output)
    reports {
        html.isEnabled = true
        xml.isEnabled = false
        csv.isEnabled = false
    }
}

tasks.register<JacocoReport>("jacocoRootReport") {
    val sourceDirs = subprojects.map { project -> project.sourceSets.main.get().allSource.srcDirs }
    dependsOn(subprojects.map { project -> project.tasks.test })
    sourceDirectories.setFrom(sourceDirs)
    additionalSourceDirs.setFrom(sourceDirs)
    classDirectories.setFrom(subprojects.map { project -> project.sourceSets.main.get().output })
    executionData.setFrom(subprojects.map { project -> project.tasks.jacocoTestReport.get().executionData })
    reports {
        html.isEnabled = true
        xml.isEnabled = false
        csv.isEnabled = false
    }
}

tasks.test {
    finalizedBy("jacocoRootReport")
}

Модуль build.gradle.kts

dependencies {
    implementation(project(":api"))
}

tasks {
    getByName<JacocoReport>("jacocoTestReport") {
        afterEvaluate {
            classDirectories.setFrom(files(classDirectories.files.map {
                fileTree(it) {
                    exclude("org/example/AppClass.class")
                }
            }))
        }
    }
}

Кроме того, любые отзывы, касающиеся чего-либо еще, высоко ценятся, я пытаюсь их изучить / улучшить и могу используйте some:).

[Edit # 1] Просто добавили одномодульную ветку к тому же репо, в котором работает, как предполагалось, но в режиме одного модуля.

[Edit # 2] Примечание. Я использую jacoco: 0.8.5 gradle: 6.1 с файлами конфигурации на Kotlin DSL (build.gradle.kts)

1 Ответ

0 голосов
/ 17 апреля 2020

Некоторое время go Я также застрял в процессе настройки JaCoCo с Sonarqube и придумал эту статью , которая может вам помочь.

Вот полное содержание jacoco.gradle file:

apply plugin: 'jacoco'

jacoco { toolVersion = "0.8.5" }

tasks.withType(Test) { jacoco.includeNoLocationClasses = true }

project.afterEvaluate {

    (android.hasProperty('applicationVariants')
            ? android.'applicationVariants'
            : android.'libraryVariants').all { variant ->
        def variantName = variant.name
        def unitTestTask = "test${variantName.capitalize()}UnitTest"
        def uiTestCoverageTask = "create${variantName.capitalize()}CoverageReport"

        tasks.create(name: "${unitTestTask}Coverage", type: JacocoReport, dependsOn: [
                "$unitTestTask",
                "$uiTestCoverageTask",
                ":module1:testDebugUnitTest",
                ":module2:testDebugUnitTest",
                ":moduleN:testDebugUnitTest",
        ]) {
            group = "Reporting"
            description = "Generate Jacoco coverage reports for the ${variantName.capitalize()} build"

            reports {
                html.enabled = true
                xml.enabled = true
                csv.enabled = false
            }

            def fileFilter = [
                    '**/R.class',
                    '**/R$*.class',
                    '**/BuildConfig.*',
                    '**/Manifest*.*',
                    '**/*Test*.*',
                    '**/com/example/databinding/*',
                    '**/com/example/generated/callback/*',
                    '**/android/databinding/*',
                    '**/androidx/databinding/*',
                    '**/di/module/*',
                    '**/*MapperImpl*.*',
                    '**/*$ViewInjector*.*',
                    '**/*$ViewBinder*.*',
                    '**/BuildConfig.*',
                    '**/*Component*.*',
                    '**/*BR*.*',
                    '**/Manifest*.*',
                    '**/*$Lambda$*.*',
                    '**/*Companion*.*',
                    '**/*Module.*',
                    '**/*Dagger*.*',
                    '**/*MembersInjector*.*',
                    '**/*_Factory*.*',
                    '**/*_Provide*Factory*.*',
                    '**/*Extensions*.*',
                    '**/*$Result.*', /* filtering `sealed` and `data` classes */
                    '**/*$Result$*.*'/* filtering `sealed` and `data` classes */
            ]

            classDirectories.setFrom(files([
                    fileTree(dir: "${buildDir}/tmp/kotlin-classes/${variantName}", excludes: fileFilter),
                    fileTree(dir: "$project.rootDir/module1/build/tmp/kotlin-classes/debug", excludes: fileFilter),
                    fileTree(dir: "$project.rootDir/module2/build/tmp/kotlin-classes/debug", excludes: fileFilter),
                    fileTree(dir: "$project.rootDir/moduleN/build/tmp/kotlin-classes/debug", excludes: fileFilter),
            ]))

            def coverageSourceDirs = [
                    "$project.rootDir/app/src/main/java",
                    "$project.projectDir/src/${variantName}/java",
                    "$project.rootDir/module1/src/main/java",
                    "$project.rootDir/module2/src/main/java",
                    "$project.rootDir/moduleN/src/main/java"
            ]
            additionalSourceDirs.setFrom(files(coverageSourceDirs))
            sourceDirectories.setFrom(files(coverageSourceDirs))

            def uiTestsData = fileTree(dir: "${buildDir}/outputs/code_coverage/${variantName}AndroidTest/connected/", includes: ["**/*.ec"])

            executionData(files([
                    "$project.buildDir/jacoco/${unitTestTask}.exec",
                    uiTestsData,
                    "$project.rootDir/module1/build/jacoco/testDebugUnitTest.exec",
                    "$project.rootDir/module2/build/jacoco/testDebugUnitTest.exec",
                    "$project.rootDir/moduleN/build/jacoco/testDebugUnitTest.exec"
            ]))
        }
    }
}

Вы можете проверить fileFilter для дополнительных параметров фильтрации.

Затем внутри каждого модуля вы должны импортировать jacoco.gradle как таковой:

apply from: "jacoco.gradle"
...