public static String decodeGender(String gender) {
if (gender == null) {
return null;
}
switch (gender) {
case "Male":
return "M";
case "Female":
return "F";
case "Unknown":
return "U";
default:
throw new IllegalStateException("Unknown gender type ");
}
}
And, the following JUnit test:
public void testDecodeGender() {
assertNull(decodeGender(null));
assertEquals("M", decodeGender("Male"));
assertEquals("F", decodeGender("Female"));
assertEquals("U", decodeGender("Unknown"));
try {
decodeGender("?");
fail("decodeGender should have failed");
} catch (Exception e) {
}
}
Jacoco Reports:
Line Coverage: 100%
Branch Coverage: 81%
Branch coverage is 81% because: on the "switch (gender) {" line Jacoco indicates that "3 of 14 branches missed". I'm assuming that the byte code that Java 7 produces make Jacoco think that some branches of this switch statement is missed? Am I really missing 3 branches!?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This is quite an interesting observation. From looking at the byte code one
can see how the Java compiler handles the switch on strings. Actually it is an
3-step process:
1. Switch on the hash code (3 Branches, 1 Default)
2. For each hash code do an equals (3 * 2 branches)
3. Do an final switch for the actual execution of the cases (3 Branches, 1 Default)
So we have an total of 14 branches which looks strange from the source code's
point of view. What looks even more strange is that you're missing three of
them. The explanation is step 2 where the equals method is applied additionally
after the hash code. To cover these branches also you would need to find other
strings with the same hash code. This is definitely something that might be
filtered from coverage reports in future versions of JaCoCo:
For the following Java 7 code:
public static String decodeGender(String gender) {
if (gender == null) {
return null;
}
switch (gender) {
case "Male":
return "M";
case "Female":
return "F";
case "Unknown":
return "U";
default:
throw new IllegalStateException("Unknown gender type ");
}
}
And, the following JUnit test:
public void testDecodeGender() {
assertNull(decodeGender(null));
assertEquals("M", decodeGender("Male"));
assertEquals("F", decodeGender("Female"));
assertEquals("U", decodeGender("Unknown"));
try {
decodeGender("?");
fail("decodeGender should have failed");
} catch (Exception e) {
}
}
Jacoco Reports:
Line Coverage: 100%
Branch Coverage: 81%
Branch coverage is 81% because: on the "switch (gender) {" line Jacoco indicates that "3 of 14 branches missed". I'm assuming that the byte code that Java 7 produces make Jacoco think that some branches of this switch statement is missed? Am I really missing 3 branches!?
This is quite an interesting observation. From looking at the byte code one
can see how the Java compiler handles the switch on strings. Actually it is an
3-step process:
1. Switch on the hash code (3 Branches, 1 Default)
2. For each hash code do an equals (3 * 2 branches)
3. Do an final switch for the actual execution of the cases (3 Branches, 1 Default)
So we have an total of 14 branches which looks strange from the source code's
point of view. What looks even more strange is that you're missing three of
them. The explanation is step 2 where the equals method is applied additionally
after the hash code. To cover these branches also you would need to find other
strings with the same hash code. This is definitely something that might be
filtered from coverage reports in future versions of JaCoCo:
https://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions
Cheers,
-marc
BTW, here is what the Java compiler produces from your example: