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

114

Проблема:

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

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

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

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

Официальный документы для : https://gradle.org/docs/current/userguide/jacoco_plugin.html

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

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

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

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

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

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

Плагин JaCoCo gradle exclude (не удалось заставить это работать)

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

Вопрос:

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

Джаред Берроуз
источник
Вариант третьей стороны (FD, я основатель): если вы загружаете отчеты в Codecov, вы можете игнорировать любые файлы, которые вам нравятся, в разделе функций продукта. Спасибо.
Стив Пик
@StevePeak Значит, вы можете фильтровать packagesонлайн с помощью Codecov? Также я видел то Github, что насчет Androidподдержки, я видел Java. Мне все равно придется отправлять вам все отчеты, а затем фильтровать после и фильтровать раньше.
Джаред Берроуз
Вы можете фильтровать на основе метода регулярного выражения любое поле, которое вы не хотите включать. Вся java поддерживается через отчеты Jacoco. Просто фильтрация постфактум на Codecov работает. Он запомнит ваши фильтры и применит их ко всем будущим отчетам. Спасибо!
Стив Пик
6
Мне любопытно; что делает excludesиз официальной документации на самом деле делать то? Это бесполезно?
Вивин Палиат
Это excludesне в задаче покрытия, а в тестовой задаче. Он исключает обработку файлов JaCoCo и, таким образом, запись покрытия. Вы можете использовать это, если вы не хотите записывать покрытие для некоторых классов, если вы не можете этого сделать из-за конфликта с другим инструментальным агентом или из-за того, что вы предварительно инструментировали классы. Это не исключает класс из отчета, особенно в последнем упомянутом случае, это было бы ужасной идеей.
Вампир

Ответы:

115

Спасибо Yannick Welsch:

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

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

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

Решение для моих 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

Джаред Берроуз
источник
1
@BradPitcher Нет проблем! Мне потребовалось время, чтобы найти правильный ответ. Это просто кажется таким «хакерским». Надеюсь, они придумали более приятный способ.
Джаред Берроуз,
Итак, каков правильный подход, если я просто хочу исключить один класс из пакета?
Педро Энрике,
2
Что-то вроде:exclude: ['**/*Test*.*'])
Джаред Берроуз
1
jacocoTestReportработает только с обоими jacocoи javaплагинов. Это не для Android. Пожалуйста, посмотрите мое репо для Android здесь: github.com/jaredsburrows/android-gradle-java-template/blob/…
Джаред Берроуз,
10
В 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.
Thunderforge
62

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

jacocoTestReport {
    afterEvaluate {
        classDirectories.setFrom(files(classDirectories.files.collect {
            fileTree(dir: it, exclude: 'com/exclude/**')
        }))
    }
}
уве
источник
2
Или просто используйте classDirectories.from (чтобы добавить в список вместо замещающего списка)
Мохамед Эль-Бельтаги
1
Вы добавите []после, exclude: чтобы включить несколько путей.
WesternGun
Отлично, я использую gradle 6.0.1, и это решение сработало для меня.
Dargenn
14

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

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

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

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

excludes = ["projecteuler/**"]

или

excludes += ["projecteuler/**"]

но

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

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

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

childno͡.de
источник
1
Похоже, что это дает классам 0% охват, а не пропускает их вообще. Я использую JaCoCi 0.8.5 и Gradle 6.0
tschumann
Это правильный способ указать jacoco не вмешиваться в некоторые классы, другие подходы влияют только на отчетную часть.
Брайс
9

Для 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/**'
                    ]
            )
        }))
    }
}
Анкур Шривастава
источник
6

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

afterEvaluate {
    classDirectories = files(classDirectories.files.collect {
        fileTree(dir: it, exclude: 'excluded/files/**')
    })
}
Андре Компаньо
источник
Хорошо, спасибо, что подтвердили, что мои выводы верны! Я надеюсь, что они упростят фильтрацию в будущем или просто задокументируют, как фильтровать с помощью Gradle.
Джаред Берроуз,
Есть ли способ исключить исходный набор из включения в отчет jacoco? Я хочу исключить все исходные файлы, которые находятся generated/java/вместо main/java.
Амир Пашазаде
4

Это было давно, но я только что наткнулся на это. Я боролся со всеми необходимыми исключениями. Я обнаружил, что для меня это было намного проще. Если вы следуете стилю макета проекта 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
                     ]
        )
    }
}
Рэнди
источник
Просто видел это снова. Это было взято прямо из рабочего конфига. Возможно, ваша версия Gradle и Jacoco отличалась от моей. Сожалею.
Рэнди
4

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

jacocoTestCoverageVerification {
    afterEvaluate {
        classDirectories = files(classDirectories.files.collect {
            fileTree(dir: "${project.buildDir}/classes/main",
                    exclude: ['**/packagename/**'])
        })
    }
}
эр-хан
источник
2

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

afterEvaluate {
    getClassDirectories().from(files(classDirectories.files.collect {
        fileTree(dir: it, exclude: 'com/blah/**')
    }))
}
Рийич
источник
2

Чтобы выполнить фильтрацию в отчете 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)
            })
        }

        ...
    }


Уилкинс Лианг
источник
0

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

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

Бхарат
источник
coverageExcludeClassesне похоже, что в JaCoCo / Gradle
Гас