JaCoCo Filtering Options
The JaCoCo Analyzer should allow to hook-in filters, that filters synthetic compiler constructs or code, that should not be considered for code coverage. This page is a collection of filters that might be useful.
Filters for Synthetic Compiler Constructs
For technical reasons the Java compiler sometimes creates additional byte code, that seems to have no relation to the source code. Highlighting such code in coverage reports is confusing should be filtered out.
- Synthetic Classes
- Synthetic accessor methods
- Synthetic bridge methods
- try/catch blocks for class literals like Example.class
- Control flow for synchronized statements
- Generated enum methods values() and valueOf()
- Private no arg constructors (probably with no code) in abstract class (see org.jacoco.core.JaCoCo@728)
- Anonymous class created for Enum switch (seems to be javac only). See org.jacoco.report.html.resources.Resources#getElementStyle@1006
- static initializer/constructor created for enum classes - can be merged with real code if there is an existing static initializer or constructor
- JAVA7 - Try with resource (implied call to close and exception trapping)
- JAVA7 - Switch on String (too many branches due to decision tree based on hashcode() and equals())
- JAVA7 - Multi Catch?
Filters for Code where Test Execution is Questionable or Impossible by Design
- Private, empty default constructors - assuming no calls to it
- Plain getters and setters
- Blocks that throw AssertionErrors - Entire block should be ignored if a condition (if !assertion throw new AssertionError)
- Exception exit from synchronized block - Should monitor entry/exit instructions even be counted?
Filters Based on Manual Tagging
Filters might parse source code to find lines with with special tags like
} catch (SomeException e) {
dohandle(e); // $COVERAGE-IGNORE$
}
In such a case all blocks overlapping with the tagged line could be ignored.
Exception exit from synchronized block
public final void reset() {
synchronized (store) {
... do something
} // <-- This line shows up as partially covered if the previous line doesn't throw an exception
}
Examples
The following example creates an anonymous class Foo$1 when compiled with JDK 5.0, but does not with ECJ or JDK 6.0. Adding in the constructor also stops creation of the class.
public class Test {
private class Foo {
/* public Foo() {} */
public void run() {}
}
public void execute() {
new Foo().run();
}
}
Pitfalls
The access flags reported by ClassReader does not include pseudo access flags that are stored in code attributes. It seems as if the correct access flags are only reported during the visit methods of ClassVisitor. To make things more interesting, you only get the right flags for inner classes after visit inner has been called (which happens after visit and visit source).