Filtrar informes de cobertura de JaCoCo con Gradle

113

Problema:

Tengo un proyecto con y quiero poder filtrar ciertas clases y / o paquetes.

Documentación relacionada:

He leído la siguiente documentación:

Oficial sitio: http://www.eclemma.org/jacoco/index.html

Oficial docs para : https://gradle.org/docs/current/userguide/jacoco_plugin.html

Oficial Githubproblemas, trabajando en la cobertura: https://github.com/jacoco/jacoco/wiki/FilteringOptions https://github.com/jacoco/jacoco/issues/14

Enlaces relacionados de StackOverflow:

JaCoCo & Gradle - Opciones de filtrado (Sin respuesta)

Excluir paquetes del informe de Jacoco usando Sonarrunner y Gradle (sin usar)

JaCoCo: excluir JSP del informe (parece funcionar para, Estoy usando )

Configuración de Maven Jacoco: excluir clases / paquetes del informe que no funciona (parece funcionar para, Estoy usando )

Exclusión del complemento gradle de JaCoCo (No se pudo hacer que esto funcione)

Gradle Jacoco: los informes de cobertura incluyen clases excluidas en la configuración (parece muy cercano, se usó doFirst, no funcionó para mí)

Ejemplo de lo que he probado:

apply plugin: 'java'
apply plugin: 'jacoco'

buildscript {
    repositories {
        mavenCentral()
        jcenter()
    }
}

repositories {
    jcenter()
}

jacocoTestReport {
    reports {
        xml {
            enabled true // coveralls plugin depends on xml format report
        }

        html {
            enabled true
        }
    }

    test {
        jacoco {
            destinationFile = file("$buildDir/jacoco/jacocoTest.exec")
            classDumpFile = file("$buildDir/jacoco/classpathdumps")
            excludes = ["projecteuler/**"] // <-- does not work
            // excludes = ["projecteuler"]
        }
    }
}

Pregunta:

¿Cómo puedo excluir ciertos paquetes y clases al generar el informes de cobertura?

Jared Burrows
fuente
Una opción de terceros (FD soy el fundador de): si carga informes a Codecov , puede ignorar cualquier archivo que desee después del hecho en la sección de características del producto. Gracias.
Steve Peak
@StevePeak ¿Entonces puedes filtrar por packagesInternet usando Codecov? Además, vi el Github, qué pasa con el Androidapoyo, vi Java. Debería tener que enviarte todos los informes y luego filtrar después y filtrar antes.
Jared Burrows
Puede filtrar en función de un método de expresión regular de cualquier archivo que no desee incluir. Todo Java es compatible con los informes de Jacoco. Simplemente filtrar después del hecho en Codecov funciona. Recordará sus filtros y los aplicará a todos los informes futuros. ¡Gracias!
Steve Peak
6
Soy curioso; lo que hace el excludesde la documentación oficial de hecho lo hacen , entonces? ¿Es bastante inútil?
Vivin Paliath
Eso excludesno está en la tarea de cobertura, sino en la tarea de prueba. Excluye archivos de ser instrumentados por JaCoCo y por lo tanto la cobertura se registra. Puede usar esto si no desea registrar la cobertura de algunas clases, si no puede debido a algún conflicto con otro agente de instrumentación o porque instrumentó previamente las clases. Esto no excluirá a una clase del informe, especialmente en el último caso mencionado, sería una idea horrible.
Vampiro

Respuestas:

115

Gracias a Yannick Welsch:

Después de buscar en Google, leer los documentos de Gradle y revisar las publicaciones más antiguas de StackOverflow, encontré esta respuesta en el Oficial foros!

jacocoTestReport {
    afterEvaluate {
        classDirectories = files(classDirectories.files.collect {
            fileTree(dir: it, exclude: 'com/blah/**')
        })
    }
}

Fuente: https://issues.gradle.org/browse/GRADLE-2955

Solución a mi build.gradlepara proyectos Java / Groovy:

apply plugin: 'java'
apply plugin: 'jacoco'

jacocoTestReport {
    reports {
        xml {
            enabled true // coveralls plugin depends on xml format report
        }

        html {
            enabled true
        }
    }

    afterEvaluate {
        classDirectories = files(classDirectories.files.collect {
            fileTree(dir: it,
                    exclude: ['codeeval/**',
                              'crackingthecode/part3knowledgebased/**',
                              '**/Chapter7ObjectOrientedDesign**',
                              '**/Chapter11Testing**',
                              '**/Chapter12SystemDesignAndMemoryLimits**',
                              'projecteuler/**'])
        })
    }
}

Como puede ver, pude agregar más exclude:para filtrar algunos paquetes.

Fuente: https://github.com/jaredsburrows/CS-Interview-Questions/blob/master/build.gradle

Tareas personalizadas para otros proyectos como Android:

apply plugin: 'jacoco'

task jacocoReport(type: JacocoReport) {
    reports {
        xml {
            enabled true // coveralls plugin depends on xml format report
        }

        html {
            enabled true
        }
    }

    afterEvaluate {
        classDirectories = files(classDirectories.files.collect {
            fileTree(dir: it,
                    exclude: ['codeeval/**',
                              'crackingthecode/part3knowledgebased/**',
                              '**/Chapter7ObjectOrientedDesign**',
                              '**/Chapter11Testing**',
                              '**/Chapter12SystemDesignAndMemoryLimits**',
                              'projecteuler/**'])
        })
    }
}

Fuente: https://github.com/jaredsburrows/android-gradle-java-app-template/blob/master/gradle/quality.gradle#L59

Jared Burrows
fuente
1
@BradPitcher ¡No hay problema! Me tomó un tiempo encontrar la respuesta correcta. Parece tan "hackish". Espero que se les ocurra una forma mejor.
Jared Burrows
Entonces, ¿cuál es el enfoque correcto si solo quiero excluir una clase del paquete?
Pedro Henrique
2
Algo como:exclude: ['**/*Test*.*'])
Jared Burrows
1
jacocoTestReportsolo funciona con complementos jacocoy java. Esto no es para Android. Consulte mi repositorio aquí para Android: github.com/jaredsburrows/android-gradle-java-template/blob/…
Jared Burrows
9
Los classDirectories =resultados en esta advertencia. The JacocoReportBase.setClassDirectories(FileCollection) method has been deprecated. This is scheduled to be removed in Gradle 6.0. Use getClassDirectories().from(...). Sería genial mostrar una solución compatible con Gradle 6.0.
Thunderforge
60

Para la versión 5.x de Gradle, classDirectories = files(...)da una advertencia de obsolescencia y no funciona en absoluto a partir de Gradle 6.0 Esta es la forma no obsoleta de excluir clases:

jacocoTestReport {
    afterEvaluate {
        classDirectories.setFrom(files(classDirectories.files.collect {
            fileTree(dir: it, exclude: 'com/exclude/**')
        }))
    }
}
uwe
fuente
2
O simplemente use classDirectories.from (para agregar a la lista en lugar de anular la lista)
Mohamed El-Beltagy
1
Agregará []después exclude: para incluir varias rutas.
WesternGun
Excelente, uso gradle 6.0.1 y esta solución me funcionó.
Dargenn
14

para mí, está bien trabajar con

test {
  jacoco {
    excludes += ['codeeval/**',
                 'crackingthecode/part3knowledgebased/**',
                 '**/Chapter7ObjectOrientedDesign**',
                 '**/Chapter11Testing**',
                 '**/Chapter12SystemDesignAndMemoryLimits**',
                 'projecteuler/**']
  }
}

como se indica en la documentación https://docs.gradle.org/current/userguide/jacoco_plugin.html#N16E62 y se preguntó inicialmente, por lo que la respuesta es:

así que si me preguntas: no es una cuestión de

excludes = ["projecteuler/**"]

o

excludes += ["projecteuler/**"]

pero

excludes = ["**/projecteuler/**"]

para excluir un paquete *.projecteuler.*

y test {}a nivel de proyecto, no anidado enjacocoTestReport

childno͡.de
fuente
1
Esto parece dar a las clases una cobertura del 0% en lugar de omitirlas por completo. Estoy usando JaCoCi 0.8.5 y Gradle 6.0
tschumann
Esta es la forma correcta de decirle a jacoco que no se entrometa en algunas clases, otros enfoques solo afectan la parte de informes.
Brice
9

Para Gradle6 Use algo como a continuación, porque hicieron classDirectories as final, no podemos reasignarlo, pero existe un método de establecimiento classDirectories.setFromque se puede utilizar

    jacocoTestReport {
    reports {
        xml.enabled true
        html.enabled true
        html.destination file("$buildDir/reports/jacoco")
    }

    afterEvaluate {
        classDirectories.setFrom(files(classDirectories.files.collect {
            fileTree(dir: it,
                    exclude: ['**/server/**',
                              '**/model/**',
                              '**/command/**'
                    ]
            )
        }))
    }
}
Ankur Srivastava
fuente
6

Aquí hay una solución para este problema en ANT. Esto se puede adaptar a Gradle agregando lo siguiente debajo de la jacocoTestReporttarea. Aunque esto no está realmente documentado por jacoco, parece ser la única forma de filtrar los resultados de la prueba por ahora.

afterEvaluate {
    classDirectories = files(classDirectories.files.collect {
        fileTree(dir: it, exclude: 'excluded/files/**')
    })
}
Andre Compagno
fuente
Muy bien, gracias por confirmar que mis hallazgos son correctos. Espero que faciliten el filtrado en el futuro o simplemente documenten cómo filtrar con Gradle.
Jared Burrows
¿Hay alguna forma de excluir un conjunto de fuentes de la inclusión en el informe jacoco? Quiero excluir todos los archivos fuente que se encuentran en generated/java/lugar de main/java.
Amir Pashazadeh
4

Esto ha estado fuera por un tiempo, pero me encontré con esto. Estaba luchando con todas las exclusiones necesarias. Descubrí que era algo mucho más simple para mí. Si sigue el estilo de diseño del proyecto Maven / src / main / java y / src / test / java, simplemente necesita poner buildDir / classes / main en su configuración de classDirectories así:

afterEvaluate {
    jacocoTestReport {
        def coverageSourceDirs = ['src/main/java']
        reports {
            xml.enabled false
            csv.enabled false
            html.destination "${buildDir}/reports/jacocoHtml"
        }
        sourceDirectories = files(coverageSourceDirs)
        classDirectories = fileTree(
                dir: "${project.buildDir}/classes/main",
                excludes: [
                      //whatever here like JavaConfig etc. in /src/main/java
                     ]
        )
    }
}
Cachondo
fuente
Acabo de ver esto de nuevo. Esto se tomó directamente de una configuración de trabajo. Quizás tu versión de Gradle y Jacoco fuera diferente a la mía. Lo siento.
Randy
4

El siguiente código también excluye las clases de la verificación de cobertura:

jacocoTestCoverageVerification {
    afterEvaluate {
        classDirectories = files(classDirectories.files.collect {
            fileTree(dir: "${project.buildDir}/classes/main",
                    exclude: ['**/packagename/**'])
        })
    }
}
er-han
fuente
2

algunos comentarios mencionaron la advertencia de desaprobación. para resolver solo usa el getter:

afterEvaluate {
    getClassDirectories().from(files(classDirectories.files.collect {
        fileTree(dir: it, exclude: 'com/blah/**')
    }))
}
riiich
fuente
2

Para filtrar en el informe jacoco, la exclusión debe realizarse en dos tareas jacocoTestReporty jacocoTestCoverageVerification.

Código de muestra

    def jacocoExclude = ['**/example/**', '**/*Module*.class']

    jacocoTestReport {
        afterEvaluate {
            getClassDirectories().setFrom(classDirectories.files.collect {
                fileTree(dir: it, exclude: jacocoExclude)
            })
        }
    }

    jacocoTestCoverageVerification {
        afterEvaluate {
            getClassDirectories().setFrom(classDirectories.files.collect {
                fileTree(dir: it, exclude: jacocoExclude)
            })
        }

        ...
    }


WIlkins LIang
fuente
0

agregue la siguiente configuración en el archivo gradle.properties

coverageExcludeClasses=["com.example.package.elasticsearch.*", "com.example.package2.*",]

Bharat
fuente
coverageExcludeClassesno parece ser una cosa en JaCoCo / Gradle
Gus