I'm wondering whether measuring conditional code coverage by current tools for Java are not obsolete since Java 8 came up. With Java 8's Optional
and Stream
we can often avoid code branches/loops, which makes it easy to get very high conditional coverage without testing all possible execution paths. Let's compare old Java code with Java 8 code :
Before Java 8:
public String getName(User user) {
if (user != null) {
if (user.getName() != null) {
return user.getName();
}
}
return "unknown";
}
There are 3 possible execution paths in the above method. In order to get 100% of conditional coverage we need to create 3 unit tests.
Java 8:
public String getName(User user) {
return Optional.ofNullable(user)
.map(User::getName)
.orElse("unknown");
}
In this case, branches are hidden and we only need 1 test to get 100% coverage and it doesn't matter which case we will test. Though there are still the same 3 logical branches which should be covered I believe. I think that it makes conditional coverage statistics completely untrusted these days.
Does it make sense to measure conditional coverage for Java 8 code? Are there any other tools spotting undertested code?
getName
? It seems to be that ifuser
is null, it should return "unknown". Ifuser
is not null anduser.getName()
is null, it should return "unknown". Ifuser
is not null anduser.getName()
is not null, it should return that. So you would unit-test those three cases because that's what the contract ofgetName
is about. You seem to be doing it backward. You don't want to see the branches and write the tests according to those, you want to write your tests according to your contract, and ensure the contract is fullfilled. That's when you have good coverage.