Zastanawiam się, czy pomiar pokrycia kodu warunkowego przez obecne narzędzia dla Java nie jest przestarzały od czasu pojawienia się Java 8. Z Java 8 użytkownika Optional
i Stream
często możemy uniknąć kodu rozgałęzień / pętle, co sprawia, że łatwo dostać bardzo wysoki zasięg bez warunkowego testowanie wszystkich możliwych ścieżek wykonania. Porównajmy stary kod Java z kodem Java 8:
Przed Javą 8:
public String getName(User user) {
if (user != null) {
if (user.getName() != null) {
return user.getName();
}
}
return "unknown";
}
W powyższej metodzie istnieją 3 możliwe ścieżki wykonania. Aby uzyskać 100% zasięgu warunkowego, musimy utworzyć 3 testy jednostkowe.
Java 8:
public String getName(User user) {
return Optional.ofNullable(user)
.map(User::getName)
.orElse("unknown");
}
W tym przypadku gałęzie są ukryte i potrzebujemy tylko 1 testu, aby uzyskać 100% pokrycia i nie ma znaczenia, który przypadek przetestujemy. Chociaż nadal istnieją te same 3 logiczne gałęzie, które należy uwzględnić, wierzę. Myślę, że sprawia to, że statystyki pokrycia warunkowego są obecnie całkowicie niezaufane.
Czy ma sens mierzenie zasięgu warunkowego dla kodu Java 8? Czy są jakieś inne narzędzia wykrywające kod, który został sprawdzony?
źródło
getName
? Wydaje się, że jeśliuser
jest zerowy, powinien zwrócić „nieznane”. Jeśliuser
nie jest zerowy iuser.getName()
jest zerowy, powinien zwrócić „nieznany”. Jeśliuser
nie jest zerowe iuser.getName()
nie jest zerowe, powinno to zwrócić. Więc przetestowałbyś te trzy przypadki, ponieważ o to właśnie chodzi w umowiegetName
. Wygląda na to, że robisz to wstecz. Nie chcesz widzieć gałęzi i pisać testów zgodnie z nimi, chcesz pisać testy zgodnie z umową i upewnić się, że umowa jest wypełniona. To wtedy masz dobry zasięg.Odpowiedzi:
Nic mi nie wiadomo. Próbowałem uruchomić kod, który masz przez JaCoCo (aka EclEmma) dla pewności, ale pokazuje 0 gałęzi w
Optional
wersji. Nie znam żadnej metody jego skonfigurowania, aby powiedzieć inaczej. Jeśli skonfigurowałeś go tak, aby zawierał również pliki JDK, teoretycznie pokazywałby rozgałęzieniaOptional
, ale myślę, że głupio byłoby zacząć weryfikować kod JDK. Musisz tylko założyć, że to prawda.Myślę jednak, że zasadniczą kwestią jest uświadomienie sobie, że dodatkowe gałęzie, które posiadałeś przed Javą 8, były w pewnym sensie sztucznie stworzonymi gałęziami. To, że nie istnieją już w Javie 8, oznacza po prostu, że masz odpowiednie narzędzie do tego zadania (w tym przypadku
Optional
). W kodzie wcześniejszym niż Java 8 trzeba było napisać dodatkowe testy jednostkowe, aby mieć pewność, że każda gałąź kodu zachowuje się w akceptowalny sposób - a to staje się nieco ważniejsze w częściach kodu, które nie są trywialne, jak w przypadkuUser
/getName
przykład.W kodzie Java 8 zamiast tego ufasz JDK, że kod działa poprawnie. Tak jak należy, należy traktować tę
Optional
linię tak, jak traktują ją narzędzia pokrycia kodu: 3 linie z 0 gałęziami. To, że w poniższym kodzie znajdują się inne wiersze i gałęzie, jest czymś, na co wcześniej nie zwracałeś uwagi, ale istnieje za każdym razem, gdy używasz czegoś takiego jakArrayList
lubHashMap
.źródło
if
inull
nadal są części języka ;-) To wciąż możliwe, aby napisać kod w starym stylu i przejśćnull
użytkownik lub użytkownik onull
nazwie. Twoje testy powinny po prostu udowodnić, że kontrakt jest spełniony, niezależnie od sposobu wdrożenia metody. Chodzi o to, że nie ma narzędzia, które powiedziałoby ci, czy w pełni przetestowałeś umowę.Optional
(i powiązane z nimi metody), nie musisz ich już testować. Nie w ten sam sposób, w jaki testowałeśif-else
: każdeif
było potencjalnym polem minowym.Optional
i podobne funkcjonalne idiomy są już zakodowane i gwarantują, że cię nie potkniesz, więc zasadniczo istnieje „gałąź”, która zniknęła.Optional
. Jak powiedział, logicznie powinniśmy nadal sprawdzać, czygetName()
obsługuje różne możliwe dane wejściowe w zamierzony sposób, niezależnie od jego implementacji. Trudniej to ustalić bez narzędzi pokrycia kodu, które pomogłyby w wersji sprzed JDK8.if-else
ponieważ każda z tych konstrukcji jest całkowicie ad-hoc. W przeciwieństwie do tegoOptional
,orElse
,map
, etc, są już przetestowane. W efekcie gałęzie „znikają”, gdy używasz silniejszych idiomów.