Отфильтруйте отчеты о покрытии JaCoCo с помощью Gradle

Проблема:

У меня есть проект с jacoco, и я хочу быть возможность фильтровать определенные классы и / или пакеты.

Связанная документация:

Я прочитал следующую документацию:

Официальный сайт jacoco: http://www.eclemma.org/jacoco/index.html

Официальные jacoco для gradle: https://gradle.org/docs/current/userguide/jacoco_plugin.html

Официальные jacoco Github, работа над освещением : https://github.com/jacoco/jacoco/wiki/FilteringOptions https://github.com/jacoco/jacoco/issues/14

Связанные ссылки на StackOverflow:

JaCoCo & Gradle - параметры фильтрации (нет ответа)

Исключить пакеты из отчета Jacoco с помощью Sonarrunner и Gradle ( Без использования сонар)

JaCoCo - исключить JSP из отчета (похоже, работает для maven, я использую gradle)

Конфигурация Maven Jacoco - исключить классы / пакеты из отчета, не работающего (похоже, это работает для maven , Я использую gradle)

Исключить плагин JaCoCo gradle (не удалось заставить это работать)

Gradle Jacoco - отчеты о покрытии включают классы, исключенные из конфигурации (Вроде очень близко, использовал doFirst, у меня не сработало)

Пример того, что я пробовал:

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

Вопрос:

Как мне исключить определенные пакеты и классы при создании jacoco отчеты о покрытии?


person Jared Burrows    schedule 27.04.2015    source источник
comment
Вариант третьей стороны (FD, я основатель): если вы загружаете отчеты в Codecov, вы можете игнорировать любые файлы, которые вам нравятся, в разделе функций продукта. Спасибо.   -  person Steve Peak    schedule 04.05.2015
comment
@StevePeak Значит, вы можете фильтровать по packages онлайн, используя Codecov? Еще видел Github, насчет поддержки Android видел Java. Мне все равно придется отправлять вам все отчеты, а затем фильтровать после и фильтровать раньше.   -  person Jared Burrows    schedule 06.05.2015
comment
Вы можете фильтровать на основе метода регулярного выражения любое поле, которое вы не хотите включать. Вся java поддерживается через отчеты Jacoco. Просто фильтрация постфактум на Codecov работает. Он запомнит ваши фильтры и применит их ко всем будущим отчетам. Спасибо!   -  person Steve Peak    schedule 06.05.2015
comment
Мне любопытно; что же тогда на самом деле делает excludes из официальной документации? Это бесполезно?   -  person Vivin Paliath    schedule 30.10.2015
comment
Этот excludes находится не в задаче покрытия, а в тестовой задаче. Он исключает обработку файлов JaCoCo и, таким образом, запись покрытия. Вы можете использовать это, если вы не хотите записывать покрытие для некоторых классов, если вы не можете из-за конфликта с другим инструментальным агентом или из-за того, что вы предварительно инструментировали классы. Это не исключает класс из отчета, особенно в последнем упомянутом случае, это было бы ужасной идеей.   -  person Vampire    schedule 25.09.2019


Ответы (15)


Спасибо, Yannick Welsch:

После поиска в Google, чтения документов Gradle и просмотра более старых сообщений StackOverflow я нашел этот ответ в официальном gradle форумы!

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

Источник: https://issues.gradle.org/browse/GRADLE-2955

Для более старых версий gradle ‹5.x может потребоваться использовать classDirectories = files(classDirectories.files.collect { вместо classDirectories.setFrom

Решение моего build.gradle для проектов 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/**'])
        })
    }
}

Как видите, мне удалось добавить больше в exclude:, чтобы отфильтровать несколько пакетов.

Источник: https://github.com/jaredsburrows/CS-Interview-Questions/blob/master/build.gradle

Пользовательские задачи для других проектов, таких как 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/**'])
        })
    }
}

Источник: https://github.com/jaredsburrows/android-gradle-java-app-template/blob/master/gradle/quality.gradle#L59

person Jared Burrows    schedule 27.04.2015
comment
@BradPitcher Нет проблем! Мне потребовалось время, чтобы найти правильный ответ. Это кажется таким хакерским. Надеюсь, они придумают более приятный способ. - person Jared Burrows; 27.05.2015
comment
Итак, каков правильный подход, если я просто хочу исключить один класс из пакета? - person Pedro Henrique; 20.10.2015
comment
Что-то вроде: exclude: ['**/*Test*.*']) - person Jared Burrows; 20.10.2015
comment
Я получаю сообщение об ошибке Gradle DSL method not found: 'jacocoTestReport ()'. Что могло быть не так? - person Asker; 25.01.2016
comment
@Asker, похоже, вы не применяете плагин: apply plugin: jacoco. - person Jared Burrows; 25.01.2016
comment
Я добавил применить плагин: 'jacoco' сразу после применения плагина: 'com.android.application'. Думаю, все должно быть хорошо? - person Asker; 25.01.2016
comment
теперь я перезапустил студию Android и получил следующую ошибку: не удается получить файлы свойств для нулевого объекта. Любые идеи? - person Asker; 25.01.2016
comment
jacocoTestReport работает только с плагинами jacoco и java. Это не для Android. Пожалуйста, посмотрите мое репо для Android здесь: github. com / jaredsburrows / android-gradle-java-template / blob / - person Jared Burrows; 25.01.2016
comment
@JaredBurrows Привет, спасибо за ответ. Как мне запустить мои инструментальные тесты с этой настройкой? Они сохраняются в этой папке app \ src \ androidTest. - person Asker; 25.01.2016
comment
@JaredBurrows эта ссылка для решения для Android не работает. Не могли бы вы поделиться им еще раз или добавить к своему ответу? Спасибо - person sttaq; 26.10.2016
comment
@sttaq Спасибо. Я добавил его в ответ и проверил здесь: github.com/jaredsburrows/android-gradle-java-app-template/blob/. - person Jared Burrows; 26.10.2016
comment
Боковое примечание - я обнаружил, что исключение **/*Constants*.* (использование подстановочного знака для расширения) исключает файл с именем Constants.java, а **/*Constants*.java (явно предоставляющее расширение) - нет. - person Wonko the Sane; 26.05.2017
comment
В моем случае это НЕ ДЕЙСТВИТЕЛЬНО исключает их из расчета, а просто не показывает их в отчете. это нужно делать под beforeEvaluate? - person Aditya Peshave; 31.10.2017
comment
classDirectories = приводит к этому предупреждению. The JacocoReportBase.setClassDirectories(FileCollection) method has been deprecated. This is scheduled to be removed in Gradle 6.0. Use getClassDirectories().from(...). Было бы здорово показать решение, совместимое с Gradle 6.0. - person Thunderforge; 16.08.2019
comment
получение Cannot set the value of read-only property 'classDirectories' for task ':jacocoTestReport' of type org.gradle.testing.jacoco.tasks.JacocoReport с использованием этой конфигурации. Использование Gradle 5.6 и Java 8 - person user9869932; 06.11.2020

Для Gradle версии 5.x classDirectories = files(...) выдает предупреждение об устаревании и вообще не работает, начиная с Gradle 6.0. Это нерекомендованный способ исключения классов:

jacocoTestReport {
    afterEvaluate {
        classDirectories.setFrom(files(classDirectories.files.collect {
            fileTree(dir: it, exclude: 'com/exclude/**')
        }))
    }
}
person uwe    schedule 16.01.2019
comment
Или просто используйте classDirectories.from (чтобы добавить в список вместо переопределения списка) - person Mohamed El-Beltagy; 02.07.2019
comment
Вы добавите [] после exclude: , чтобы включить несколько путей. - person WesternGun; 29.10.2019
comment
Отлично, я использую gradle 6.0.1, и это решение сработало для меня. - person Dargenn; 24.04.2020
comment
это сработало, может кто-нибудь объяснить, что именно происходит - person krishna110293; 01.12.2020
comment
Я изменил принятый ответ, чтобы отразить это изменение - person tkruse; 08.01.2021
comment
Или даже используйте getClassDirectories().from(). - person gsmachado; 17.03.2021
comment
Я пытаюсь исключить свои dtos и использую приведенный ниже код. Но это не работает. Дайте мне знать, если я что-то упустил. Пробовал в build.gradle jacocoTestReport {afterEvaluate {classDirectories.setFrom (files (classDirectories.files.collect {fileTree (dir: it, exclude: '/ dto /')}))}} - person Karthik Reddy; 22.04.2021

для меня нормально работать с

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

как указано в документации https://docs.gradle.org/current/userguide/jacoco_plugin.html#N16E62 и изначально задал такой ответ:

так что если вы спросите меня: это не вопрос

excludes = ["projecteuler/**"]

or

excludes += ["projecteuler/**"]

но

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

исключить пакет *.projecteuler.*

и test {} на уровне проекта, не вложенные в jacocoTestReport

person childno͡.de    schedule 21.06.2016
comment
Похоже, что это дает классам 0% охват, а не пропускает их полностью. Я использую JaCoCi 0.8.5 и Gradle 6.0 - person tschumann; 29.10.2019
comment
Это правильный способ указать jacoco не вмешиваться в некоторые классы, другие подходы влияют только на отчетную часть. - person Brice; 12.06.2020

Для Gradle6 Используйте что-то вроде ниже, потому что они сделали classDirectories as final, мы не можем переназначить его, но существует метод установки classDirectories.setFrom, который можно использовать

    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/**'
                    ]
            )
        }))
    }
}
person Ankur Srivastava    schedule 24.12.2019
comment
Я пытаюсь использовать приведенный ниже фрагмент в build.gradle, чтобы исключить мои dtos, но он не работает. Я использую версию Gradle 6.6.1. Сообщите мне, если какие-либо изменения 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: ['/ dto /'])}))}} - person Karthik Reddy; 22.04.2021

Вот решение этой проблемы в ANT. Это можно адаптировать к gradle, добавив следующее в задачу jacocoTestReport. Хотя это на самом деле не задокументировано jacoco, на данный момент это единственный способ отфильтровать результаты теста.

afterEvaluate {
    classDirectories = files(classDirectories.files.collect {
        fileTree(dir: it, exclude: 'excluded/files/**')
    })
}
person Andre Compagno    schedule 07.05.2015
comment
Хорошо, спасибо, что подтвердили, что мои выводы верны! Я надеюсь, что они упростят фильтрацию в будущем или просто задокументируют, как фильтровать с помощью Gradle. - person Jared Burrows; 07.05.2015
comment
Есть ли способ исключить исходный набор из включения в отчет jacoco? Я хочу исключить все исходные файлы, которые находятся в generated/java/ вместо main/java. - person Amir Pashazadeh; 07.03.2018
comment
Это не сработает для чистой сборки. afterEvaluate запускается на этапе настройки Gradle, который происходит до выполнения каких-либо задач и до того, как какие-либо классы были скомпилированы. Таким образом, каталоги классов будут пустыми - person lance-java; 26.09.2020

Чтобы выполнить фильтрацию в отчете jacoco, необходимо выполнить исключение в двух задачах jacocoTestReport и jacocoTestCoverageVerification.

образец кода

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

        ...
    }



person WIlkins LIang    schedule 15.07.2020

Это было давно, но я только что наткнулся на это. Я боролся со всеми необходимыми исключениями. Я обнаружил, что для меня это было намного проще. Если вы следуете стилю макета проекта Maven / src / main / java и / src / test / java, вам просто нужно поместить buildDir / classes / main в свой classDirectories вот так:

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
                     ]
        )
    }
}
person Randy    schedule 01.03.2016
comment
Просто видел это снова. Это было взято прямо из рабочего конфига. Возможно, ваша версия Gradle и Jacoco отличалась от моей. Извините. - person Randy; 09.10.2018

Приведенный ниже код также исключает классы из проверки покрытия:

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

Для меня я должен исключить в 2-х местах

jacocoTestReport {
    dependsOn test // tests are required to run before generating the report


    afterEvaluate {
        excludedClassFilesForReport(classDirectories)
    }
}

jacocoTestCoverageVerification {

    afterEvaluate {
        excludedClassFilesForReport(classDirectories)
    }
}

private excludedClassFilesForReport(classDirectories) {
    classDirectories.setFrom(files(classDirectories.files.collect {
        fileTree(dir: it,
            exclude: [
                    'com/test/a/config/**',
                    'com/test/b/constant/**',
                    'com/test/c/MainApp.class'
            ]
    )
}))
}
person sendon1982    schedule 12.11.2020

Для тех, кто все еще ломает голову над тем, чтобы отфильтровать определенные пакеты из отчета о покрытии, вот конфигурация, которая работает для меня с использованием самых последних библиотек.

   Build tool: Gradle 6.5 (also tried for 6.7)
   Coverage Tool: Jacoco 0.8.5

На что следует обратить внимание / Обоснования

  • afterScript не требуется
  • Необходимо исключить его дважды, один для создания отчета и проверки покрытия.
  • Intellij IDE рекомендует использовать параметр excludes вместо exclude. Любой из них отлично работает
  • Предоставляя регулярное выражение, обязательно укажите файлы .class, а не файлы .java.
  • Post Gradle 5, classDirectories является полем только для чтения, поэтому используйте classDirectories.setFrom
jacocoTestReport {
    doLast {
        println("See report file://${project.rootDir}/build/reports/jacoco/test/html/index.html")
    }
    excludedClassFilesForReport(classDirectories)
}

jacocoTestCoverageVerification {
    excludedClassFilesForReport(classDirectories)
    violationRules {
        rule {
            limit {
                minimum = 0.55
            }
        }
    }
}

private excludedClassFilesForReport(classDirectories) {
    classDirectories.setFrom(files(classDirectories.files.collect {
        fileTree(dir: it, exclude: [
                '**/common/apigateway/*.class',a
                '**/common/*/client/*Client*.class',
                '**/configuration/*ClientConfiguration.class',
                '**/model/search/*SearchService.class'
        ])
    }))
}

check.dependsOn jacocoTestCoverageVerification
person Shreyas Patankar    schedule 29.04.2021

в некоторых комментариях упоминалось предупреждение об устаревании. для решения просто используйте геттер:

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

Для тех, кто сходит с ума, ища этот ответ в Kotlin DSL, вот он:

val jacocoExclude = listOf("**/entities/**", "**/dtos/**")
jacocoTestReport {
    reports {
        xml.isEnabled = true
        csv.isEnabled = false
    }
    classDirectories.setFrom(classDirectories.files.map {
        fileTree(it).matching {
            exclude(jacocoExclude)
        }
        })
}
test {
    useJUnitPlatform()
    systemProperty("gradle.build.dir", project.buildDir)
    finalizedBy(jacocoTestReport)
    extensions.configure(JacocoTaskExtension::class) {
        excludes = jacocoExclude
    }
}
person sbzoom    schedule 13.04.2021

для пользователей Kotlin вот что я использовал (gradle 6.7)

build.gradle.kts

tasks.jacocoTestReport {
    // tests are required to run before generating the report
    dependsOn(tasks.test) 
    // print the report url for easier access
    doLast {
        println("file://${project.rootDir}/build/reports/jacoco/test/html/index.html")
    }
    classDirectories.setFrom(
        files(classDirectories.files.map {
            fileTree(it) {
                exclude("**/generated/**", "**/other-excluded/**")
            }
        })
    )
}

как предлагается здесь: https://github.com/gradle/kotlin-dsl-samples/issues/1176#issuecomment-610643709

person Emarco    schedule 08.04.2021

добавьте ниже конфигурацию в файл gradle.properties

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

person Bharat    schedule 11.09.2019
comment
coverageExcludeClasses не похоже на то, что есть в JaCoCo / Gradle - person Gus; 09.07.2020

Gradle 6.8.3 выдал исключение. Cannot set the value of read-only property 'classDirectories' for task ':jacocoTestReport' of type org.gradle.testing.jacoco.tasks.JacocoReport.

поэтому я нашел способ решить проблему, используя

classDirectories.setFrom(
            fileTree(dir: "build/classes/java/main")
                    .filter({file -> !file.path.contains('/dir1')})
                    .filter({file -> !file.path.contains('/dir2')})
                    .filter({file -> !file.path.contains('/dir3')})
    )
person saif ali    schedule 02.04.2021