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?


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


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/**')
        }))
    }
}

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


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/**'
                    ]
            )
        }))
    }
}

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/**')
    })
}

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

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/**'])
        })
    }
}

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/**')
    }))
}

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)
            })
        }

        ...
    }



0

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

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


coverageExcludeClassesnão parece ser uma coisa em JaCoCo / Gradle
Gus
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.