Filtruj raporty pokrycia JaCoCo za pomocą Gradle

113

Problem:

Mam projekt z i chcę mieć możliwość filtrowania określonych klas i / lub pakietów.

Powiązana dokumentacja:

Przeczytałem następującą dokumentację:

Urzędnik site: http://www.eclemma.org/jacoco/index.html

Urzędnik dokumenty dla : https://gradle.org/docs/current/userguide/jacoco_plugin.html

Urzędnik Githubzagadnienia, praca nad zasięgiem: https://github.com/jacoco/jacoco/wiki/FilteringOptions https://github.com/jacoco/jacoco/issues/14

Powiązane łącza StackOverflow:

JaCoCo i Gradle - Opcje filtrowania (brak odpowiedzi)

Wyklucz pakiety z raportu Jacoco za pomocą Sonarrunner i Gradle (nie używa)

JaCoCo - wyklucz JSP z raportu (wydaje się, że działa w przypadku, Ja używam )

Konfiguracja Maven Jacoco - wykluczenie klas / pakietów z raportu nie działa (wydaje się działać dla, Ja używam )

Wykluczenie wtyczki JaCoCo gradle (nie udało się tego uruchomić)

Gradle Jacoco - raporty pokrycia obejmują klasy wykluczone w konfiguracji (Wydaje się bardzo zbliżone, używane doFirst, nie działały u mnie)

Przykład tego, czego próbowałem:

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

Pytanie:

Jak mogę wykluczyć niektóre pakiety i klasy podczas generowania pliku raporty zasięgu?

Jared Burrows
źródło
Opcja strony trzeciej (FD, którego jestem założycielem): Jeśli przesyłasz raporty do Codecov , możesz zignorować dowolne pliki po fakcie w sekcji funkcji produktu. Dzięki.
Steve Peak
@StevePeak Więc możesz filtrować packagesonline używając Codecov? Widziałem też Github, co z Androidobsługą, widziałem Java. Powinienem nadal wysyłać Ci wszystkie raporty, a następnie filtrować po a wcześniej filtrować.
Jared Burrows
Możesz filtrować na podstawie metody wyrażenia regularnego dowolnego pola, którego nie chcesz uwzględniać. Cała java jest obsługiwana przez raporty Jacoco. Po prostu filtrowanie po fakcie w Codecov działa. Zapamięta Twoje filtry i zastosuje je do wszystkich przyszłych raportów. Dzięki!
Steve Peak
6
Jestem ciekawy; co excludeswłaściwie robi oficjalna dokumentacja ? Czy to jest prawie bezużyteczne?
Vivin Paliath
To excludesnie dotyczy zadania pokrycia, ale zadania testowego. Wyklucza to pliki z instrumentowania przez JaCoCo, a tym samym z nagrywania relacji. Możesz tego użyć, jeśli nie chcesz rejestrować pokrycia niektórych klas, jeśli nie możesz tego zrobić z powodu konfliktu z innym agentem instrumentacji lub z powodu wcześniejszego oprzyrządowania klas. Nie wykluczy to klasy z raportu, zwłaszcza w ostatnim wymienionym przypadku byłby to okropny pomysł.
Vampire

Odpowiedzi:

115

Dzięki Yannick Welsch:

Po przeszukaniu Google, przeczytaniu dokumentów Gradle i przejrzeniu starszych postów StackOverflow, znalazłem tę odpowiedź w oficjalnym fora!

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

Źródło: https://issues.gradle.org/browse/GRADLE-2955

Rozwiązanie dla moich build.gradleprojektów 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/**'])
        })
    }
}

Jak widać, udało mi się dodać więcej exclude:, aby przefiltrować kilka pakietów.

Źródło: https://github.com/jaredsburrows/CS-Interview-Questions/blob/master/build.gradle

Niestandardowe zadania dla innych projektów, takich jak 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/**'])
        })
    }
}

Źródło: https://github.com/jaredsburrows/android-gradle-java-app-template/blob/master/gradle/quality.gradle#L59

Jared Burrows
źródło
1
@BradPitcher Nie ma problemu! Znalezienie właściwej odpowiedzi zajęło mi trochę czasu. To po prostu wydaje się takie „hakerskie”. Mam nadzieję, że wymyślą lepszy sposób.
Jared Burrows
Jakie jest więc prawidłowe podejście, jeśli chcę tylko wykluczyć jedną klasę z pakietu?
Pedro Henrique
2
Coś w rodzaju:exclude: ['**/*Test*.*'])
Jared Burrows
1
jacocoTestReportdziała tylko z wtyczkami jacocoi i java. To nie jest dla Androida. Zobacz moje repozytorium tutaj dla Androida: github.com/jaredsburrows/android-gradle-java-template/blob/…
Jared Burrows
9
Te classDirectories =wyniki w tym ostrzeżeniem. The JacocoReportBase.setClassDirectories(FileCollection) method has been deprecated. This is scheduled to be removed in Gradle 6.0. Use getClassDirectories().from(...). Byłoby wspaniale pokazać rozwiązanie kompatybilne z Gradle 6.0.
Thunderforge
61

W przypadku programu Gradle w wersji 5.x classDirectories = files(...)ostrzega o wycofaniu i nie działa w ogóle, począwszy od wersji Gradle 6.0. Jest to niezalecany sposób wykluczania klas:

jacocoTestReport {
    afterEvaluate {
        classDirectories.setFrom(files(classDirectories.files.collect {
            fileTree(dir: it, exclude: 'com/exclude/**')
        }))
    }
}
uwe
źródło
2
Lub po prostu użyj classDirectories.from (aby dołączyć do listy zamiast nadpisywania listy)
Mohamed El-Beltagy
1
Dodasz []po, exclude: aby uwzględnić kilka ścieżek.
WesternGun
Świetnie, używam gradle 6.0.1 i to rozwiązanie zadziałało.
Dargenn
14

dla mnie dobrze się pracuje z

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

jak stwierdzono w dokumentacji https://docs.gradle.org/current/userguide/jacoco_plugin.html#N16E62 i początkowo zapytano, więc odpowiedź brzmi:

więc jeśli mnie zapytasz: to nie jest kwestia

excludes = ["projecteuler/**"]

lub

excludes += ["projecteuler/**"]

ale

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

aby wykluczyć pakiet *.projecteuler.*

i test {}na poziomie projektu, nie zagnieżdżone wjacocoTestReport

childno͡.de
źródło
1
Wydaje się, że daje to klasom pokrycie na poziomie 0%, zamiast je całkowicie pomijać. Używam JaCoCi 0.8.5 i Gradle 6.0
tschumann
To właściwy sposób, aby powiedzieć Jacoco, aby nie wtrącał się do niektórych klas, inne podejścia mają wpływ tylko na część raportującą.
Brice
9

Dla Gradle6 Użyj czegoś takiego jak poniżej, ponieważ stworzyli classDirectories as final, nie możemy go ponownie przypisać, ale istnieje metoda ustawiająca, classDirectories.setFromktórą można wykorzystać

    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
źródło
6

Oto rozwiązanie tego problemu w ANT. Można to dostosować do gradle, dodając w jacocoTestReportzadaniu następujące elementy . Chociaż jacoco tak naprawdę nie jest udokumentowane, wydaje się, że na razie jest to jedyny sposób na przefiltrowanie wyników testu.

afterEvaluate {
    classDirectories = files(classDirectories.files.collect {
        fileTree(dir: it, exclude: 'excluded/files/**')
    })
}
Andre Compagno
źródło
W porządku, dziękuję za potwierdzenie, że moje ustalenia są prawidłowe! Mam nadzieję, że ułatwią one filtrowanie w przyszłości lub po prostu udokumentują sposób filtrowania za pomocą Gradle.
Jared Burrows
Czy istnieje sposób, aby wykluczyć zestaw źródłowy z uwzględnienia w raporcie jacoco? Chcę wykluczyć wszystkie pliki źródłowe, które znajdują się w generated/java/zamiast main/java.
Amir Pashazadeh
4

To było przez jakiś czas, ale właśnie się z tym spotkałem. Walczyłem ze wszystkimi potrzebnymi wykluczeniami. Okazało się, że to dla mnie coś znacznie prostszego. Jeśli podążasz za stylem projektu Maven / src / main / java i / src / test / java, po prostu musisz umieścić buildDir / classes / main w swojej konfiguracji classDirectories w następujący sposób:

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
                     ]
        )
    }
}
Niespokojny
źródło
Właśnie to widziałem. Zostało to pobrane bezpośrednio z działającej konfiguracji. Być może twoja wersja Gradle i Jacoco była inna niż moja. Przepraszam.
Randy,
4

Poniższy kod wyłącza również klasy z weryfikacji pokrycia:

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

w niektórych komentarzach wspomniano o ostrzeżeniu o wycofaniu. aby rozwiązać po prostu użyj gettera:

afterEvaluate {
    getClassDirectories().from(files(classDirectories.files.collect {
        fileTree(dir: it, exclude: 'com/blah/**')
    }))
}
riiich
źródło
2

Aby filtrować w raporcie jacoco, wykluczenie należy wykonać w dwóch zadaniach jacocoTestReporti jacocoTestCoverageVerification.

przykładowy kod

    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
źródło
0

dodaj poniższą konfigurację w pliku gradle.properties

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

Bharat
źródło
coverageExcludeClassesnie wydaje się być czymś w JaCoCo / Gradle
Gus