How would I add an annotation to exclude a method from a jacoco code coverage report?
Asked Answered
F

6

79

I have some code in Java that I want to exclude from code coverage. How would I do this? I want to be able to add an annotation. Is there a way to configure or extend jacoco (as used in gradle) to use this?

Example:

public class Something
{
    @ExcludeFromCodeCoverage
    public void someMethod() {}
}
Florous answered 15/12, 2017 at 1:58 Comment(1)
you were near, @ExcludeFromGeneratedCodeCoverage would do :DProfanatory
S
79

Since there are no direct answers to this, did a bit of research and came across this PR.

https://github.com/jacoco/jacoco/pull/822/files

  private static boolean matches(final String annotation) {
    final String name = annotation
            .substring(Math.max(annotation.lastIndexOf('/'),
                    annotation.lastIndexOf('$')) + 1);
    return name.contains("Generated")
  }

You can create any annotation with name containing "Generated". I've created the following in my codebase to exclude methods from being included in Jacoco report.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExcludeFromJacocoGeneratedReport {}

Use this annotation in your methods to exempt it from coverage as below.

public class Something
{
    @ExcludeFromJacocoGeneratedReport
    public void someMethod() {}
}
Staceestacey answered 2/4, 2021 at 11:28 Comment(16)
Have you tried this and confirmed it works?Florous
Yes @DonRhummy . I could see the methods annotated With this are skipped in Sonarcloud analysisStaceestacey
Is this required specific sonar scanner as I can see it is not working for me still the function is showing as uncover in reportHendrix
Maybe you should update Jacoco plugin versionStaceestacey
@Bacciform maybe you can post your gradle file and minimum example in a separate questionStaceestacey
@MohamedAneesA I find the workaround: Intellij code coverage (a wrapper for jacoco) fails to work. but run the raw jacoco is ok.Bacciform
Jetbrains was asked years ago to do something about this, but they still haven't. Luckily, In the run/debug configuration settings of intellij idea it is possible to specify an alternative coverage runner. And apparently intellij idea comes bundled with jacoco. So, simply select Jacoco instead of intellij idea, and the annotation will work.Wayne
I just love how you're politically capable, and made the annotation sound not like the code is "generated" (which wouldn't be true) but as if you're referring to the "generated-reports"Rustin
@Rustin :) Naming matters!Staceestacey
and to be 100% clear, the annotation name must have the word "Generated" in it for this to workTeel
So ad hoc. This should be configurable.Abutter
@DávidHorváth You can contribute, why not! :)Staceestacey
The naming is brilliant! 👏Varistor
Is there a good way to apply this to generated Hibernate methods?Roundworm
It’s good to mention that this behavior was added in version 0.8.3 and is mentioned in the release notes for the same. Here is the GitHub PR for the change: github.com/jacoco/jacoco/pull/822Redraft
does it work for anonymous class as well ? in my case if a method have an anonymous class it doesn't exclude itArillode
G
28

The new feature has been added in the 0.8.2 release of JaCoCo which filters out the classes and methods annotated with @Generated. For details please see the documentation below:

Classes and methods annotated with annotation whose retention policy is runtime or class and whose simple name is Generated are filtered out during generation of report (GitHub #731).

JaCoCo 0.8.2 Release Notes

Geochemistry answered 5/8, 2019 at 16:54 Comment(4)
This includes annotations you define in your own applications that are called Generated.Redraft
@Redraft it must include Generated in annotation class name, i.e. ExcludeFromJacocoGeneratedReport should be validUpcast
@Upcast Not according to the release notes cited in this answer. It says “whose simple name is Generated”. It’s possible the actual behavior differs from the note, or a newer release may have altered that behavior, so if you know a version that behaves as you say, please track down a place that documents it to behave that way and share it. If such documentation doesn’t exist, it is unwise to rely on undocumented behavior because the documentation represents the contractual behavior of the tool (meaning extra behavior is subject to change without notice).Redraft
@Upcast Never mind. I found it. It was changed in 0.8.3 and is mentioned in the release notes. Here is the GitHub PR that merged it: github.com/jacoco/jacoco/pull/822Redraft
C
14

Following @mohamed-anees-a approach, I got to this kotlin version:

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION)
annotation class ExcludeFromJacocoGeneratedReport
Coshow answered 2/12, 2021 at 10:49 Comment(0)
S
13

Tl;dr

Use annotation @lombok.Generated from Lombok.

Explanation

Jacoco integrates with Lombok. Code generated by Lombok is excluded from Jacoco coverage by default (see Release 0.8.0 in Jacoco changelog). You can misuse lombok.Generated at your method for it being excluded from the coverage report.

Spree answered 27/5, 2019 at 14:8 Comment(4)
Lombok uses undocumented, unofficial classes that are not guaranteed to be in every java runtime. (And that are strongly recommended not to be used)Florous
Very important to note that this is a hack workaround. Highly suggest avoiding.Brenza
How would one "extend" the @Generated annotation to be able to rename it to something like OP suggested: @ExcludeFromCodeCoverage ?Uncial
I am pretty sure you would have to patch JaCoCo for doing so.Spree
D
8

I have some code in Java that I want to exclude from code coverage. How would I do this? I want to be able to add an annotation. Is there a way to configure or extend jacoco (as used in gradle) to use this?

As of today there is no such feature in latest released version of JaCoCo (0.7.9). Only whole classes can be excluded.

On page https://github.com/jacoco/jacoco/wiki/FilteringOptions#annotation-based-filtering (which is dedicated for developers) this is recorded as an idea for future versions.

Official JaCoCo documentation contains information about how to obtain latest unreleased build as well as list of unreleased changes for next version - http://www.jacoco.org/jacoco/trunk/doc/changes.html , which includes various filters, among which filtering of methods that are generated by Lombok and Groovy and marked by annotations lombok.Generated and groovy.transform.Generated respectively. Potentially you can abuse this, but I wouldn't recommend to do so for many various reasons.

Dillard answered 15/12, 2017 at 2:25 Comment(8)
+1, but... what would be a legitimate use for such an annotation? I can't find any such example anywhere, and my feeling is that this feature in a coverage tool would only get misused and abused. If a method exists in source code and is not empty, then I think it should be accounted for in coverage analysis, even if the source code was generated by some tool. After all, the method supposedly would give some contribution to the app/system functionality, right? If so, why not test it?Davidson
@Rogério - private constructors in "static" helper classes - I don't think using reflection to force the constructor execution is the right approach...Adp
@Adp Of course calling the private constructor through Reflection is not the solution... The proper solution is for the code coverage tool to automatically filter them out; JaCoCo is already doing it for a private empty constructor.Davidson
@Rogério I'd like to not cover main() methods that are used for Q&D testing or examples of how to use the class. That naively seems like a legit use case.Pyle
@Pyle Such code (main methods for testing, examples) is best put in their own source files, to avoid polluting the production codebase. And coverage tools already support the exclusion of selected source files or classes.Davidson
I'd say, code that exists purely for GUI initialization. Or maybe I just don't know how to test itExtravasation
Is latest version of JaCoCo support this feature?N
I'd omit toString methods but these can be generated by Lombok.Ginglymus
T
6

You can set lombok.addLombokGeneratedAnnotation = true into lombok.config in the root of project. After that, all Lombok-generated code will be ignored by Jacoco.

See more in Project Lombok documentation: https://projectlombok.org/features/configuration

Tenpin answered 14/6, 2020 at 14:43 Comment(3)
Lombok uses undocumented, unofficial classes that are not guaranteed to be in every java runtime. (And that are strongly recommended not to be used)Florous
@DonRhummy I don't know if I understand your comment correctly, Lombok, is a compile time dependency/plugin and applications will be shipped with compiled code which should not include anything related to lombok. Please, let me know if I am missing something.Howland
Note that the question is not about Lombok, so this wouldn’t work for the general case. The feature you mention is documented but it simply does not help here – hence, I think, the confusing comment by @DonRhummy (copied from another answer where it really applies).Celluloid

© 2022 - 2024 — McMap. All rights reserved.