Filtrar relatórios de cobertura JaCoCo com Gradle

113

Problema:

Eu tenho um projeto com e eu quero ser capaz de filtrar certas classes e / ou pacotes.

Documentação relacionada:

Eu li a seguinte documentação:

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

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

Oficial Githubquestões, trabalhando na cobertura: https://github.com/jacoco/jacoco/wiki/FilteringOptions https://github.com/jacoco/jacoco/issues/14

Links StackOverflow relacionados:

JaCoCo & Gradle - Opções de filtragem (sem resposta)

Excluir pacotes do relatório Jacoco usando Sonarrunner e Gradle (não usando)

JaCoCo - excluir JSP do relatório (parece funcionar para, Estou usando )

Configuração Maven Jacoco - Excluir classes / pacotes do relatório que não funcionam (parece funcionar para, Estou usando )

Exclusão do plugin JaCoCo gradle (não foi possível fazer isso funcionar)

Gradle Jacoco - relatórios de cobertura incluem classes excluídas na configuração (parece muito próximo, usou doFirst, não funcionou para mim)

Exemplo do que tentei:

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"]
        }
    }
}

Questão:

Como posso excluir certos pacotes e classes ao gerar o relatórios de cobertura?

Jared Burrows
fonte
Uma opção de terceiros (FD eu sou o fundador): Se você carregar relatórios para Codecov, você pode ignorar quaisquer arquivos que desejar após o fato na seção de recursos do produto. Obrigado.
Steve Peak
@StevePeak Então você pode filtrar packagesonline usando Codecov? Além disso, eu vi o Github, o que dizer de Androidapoio, eu vi Java. Ainda devo enviar a você todos os relatórios e, em seguida, filtrar após vs filtrar antes.
Jared Burrows
Você pode filtrar com base em um método regexp de qualquer campo que não deseja incluir. Todo o java é suportado por relatórios Jacoco. Basta filtrar após o fato em obras Codecov. Ele se lembrará de seus filtros e os aplicará a todos os relatórios futuros. Obrigado!
Steve Peak
6
Estou curioso; o que a excludesdocumentação oficial realmente faz então? É praticamente inútil?
Vivin Paliath
Isso excludesnão está na tarefa de cobertura, mas na tarefa de teste. Exclui os arquivos da instrumentação da JaCoCo e, portanto, da gravação da cobertura. Você pode usar isto se não quiser gravar cobertura para algumas classes, se não puder por causa de algum conflito com outro agente de instrumentação ou porque você pré-instrumentou classes. Isso não excluirá uma turma do relatório, principalmente no último caso mencionado, seria uma ideia horrível.
Vampiro de

Respostas:

115

Graças a Yannick Welsch:

Depois de pesquisar no Google, ler os documentos do Gradle e passar por postagens mais antigas do StackOverflow, encontrei esta resposta fóruns!

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

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

Solução para meus build.gradleprojetos 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 você pode ver, fui capaz de adicionar mais exclude:para filtrar alguns pacotes.

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

Tarefas personalizadas para outros projetos, 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/**'])
        })
    }
}

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

Jared Burrows
fonte
1
@BradPitcher Sem problema! Levei um tempo para encontrar a resposta certa. Parece tão "hackeado". Espero que eles encontrem uma maneira melhor.
Jared Burrows
Então, qual é a abordagem correta se eu quiser apenas excluir uma classe do pacote?
Pedro Henrique
2
Algo como:exclude: ['**/*Test*.*'])
Jared Burrows,
1
jacocoTestReportsó funciona com plug jacoco- javains e . Isso não é para Android. Consulte meu repositório
Jared Burrows
9
Os classDirectories =resultados neste aviso. The JacocoReportBase.setClassDirectories(FileCollection) method has been deprecated. This is scheduled to be removed in Gradle 6.0. Use getClassDirectories().from(...). Seria ótimo mostrar uma solução compatível com Gradle 6.0.
Thunderforge de
60

Para o Gradle versão 5.x, o classDirectories = files(...)fornece um aviso de suspensão de uso e não funciona a partir do Gradle 6.0. Esta é a forma não obsoleta de excluir classes:

jacocoTestReport {
    afterEvaluate {
        classDirectories.setFrom(files(classDirectories.files.collect {
            fileTree(dir: it, exclude: 'com/exclude/**')
        }))
    }
}
uwe
fonte
2
Ou simplesmente use classDirectories.from (para anexar à lista em vez de substituir a lista)
Mohamed El-Beltagy
1
Você adicionará []depois exclude: para incluir vários caminhos.
WesternGun
Excelente, eu uso o gradle 6.0.1 e essa solução funcionou para mim.
Dargenn
14

para mim, tudo bem trabalhar com

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

conforme declarado na documentação https://docs.gradle.org/current/userguide/jacoco_plugin.html#N16E62 e inicialmente perguntado, então a resposta é:

então se você me perguntar: não é uma questão de

excludes = ["projecteuler/**"]

ou

excludes += ["projecteuler/**"]

mas

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

excluir um pacote *.projecteuler.*

e test {}no nível do projeto, não aninhado emjacocoTestReport

childno͡.de
fonte
1
Isso parece dar às classes uma cobertura de 0%, em vez de omiti-las completamente. Estou usando JaCoCi 0.8.5 e Gradle 6.0
tschumann
Essa é a maneira certa de dizer ao jacoco para não se intrometer em algumas aulas; outras abordagens afetam apenas a parte do relatório.
Brice
9

Para Gradle6 use algo como abaixo, porque eles fizeram classDirectories as final, não podemos reatribuí-lo, mas existe um método setter classDirectories.setFromque pode ser utilizado

    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
fonte
6

Aqui está uma solução para esse problema na ANT. Isso pode ser adaptado ao gradle adicionando o seguinte na jacocoTestReporttarefa. Embora isso não seja realmente documentado pelo jacoco, parece ser a única maneira de filtrar os resultados do teste por enquanto.

afterEvaluate {
    classDirectories = files(classDirectories.files.collect {
        fileTree(dir: it, exclude: 'excluded/files/**')
    })
}
Andre Compagno
fonte
Tudo bem, obrigado por confirmar que minhas descobertas estão corretas! Espero que eles facilitem a filtragem no futuro ou simplesmente documentem como filtrar usando o Gradle.
Jared Burrows
Existe alguma maneira de excluir um conjunto de origem da inclusão no relatório jacoco? Desejo excluir todos os arquivos de origem que estão localizados em em generated/java/vez de main/java.
Amir Pashazadeh
4

Isso já foi divulgado por um tempo, mas acabei de encontrar isso. Eu estava lutando com todas as exclusões necessárias. Achei que era algo muito mais simples para mim. Se você seguir o estilo de layout do projeto Maven / src / main / java e / src / test / java, você simplesmente precisa colocar buildDir / classes / main em sua configuração classDirectories assim:

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
                     ]
        )
    }
}
Randy
fonte
Acabei de ver isso novamente. Isso foi obtido diretamente de uma configuração de trabalho. Talvez sua versão de Gradle e Jacoco fosse diferente da minha. Desculpe.
Randy,
4

O código abaixo também exclui classes da verificação de cobertura:

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

alguns comentários mencionaram o aviso de suspensão de uso. para resolver basta usar o getter:

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

Para filtrar no relatório jacoco, a exclusão precisa ser feita em duas tarefas jacocoTestReporte jacocoTestCoverageVerification.

Código de amostra

    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
fonte
0

adicione a configuração abaixo no arquivo gradle.properties

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

Bharat
fonte
coverageExcludeClassesnão parece ser uma coisa em JaCoCo / Gradle
Gus