Ich frage mich, ob das Messen der bedingten Code-Abdeckung mit aktuellen Java-Tools nicht überholt ist, seit Java 8 verfügbar ist. Mit Java 8 ist Optional
und Stream
wir können oft vermeiden Code branches / Loops, die es einfach macht , zu bekommen sehr hohe bedingte Abdeckung ohne Prüfung aller möglichen Ausführungspfade. Vergleichen wir alten Java-Code mit Java-8-Code:
Vor Java 8:
public String getName(User user) {
if (user != null) {
if (user.getName() != null) {
return user.getName();
}
}
return "unknown";
}
Bei der obigen Methode gibt es 3 mögliche Ausführungspfade. Um 100% der bedingten Deckung zu erhalten, müssen 3 Einheitentests erstellt werden.
Java 8:
public String getName(User user) {
return Optional.ofNullable(user)
.map(User::getName)
.orElse("unknown");
}
In diesem Fall sind die Zweige ausgeblendet und wir benötigen nur einen Test, um eine 100% ige Abdeckung zu erhalten. Dabei spielt es keine Rolle, welchen Fall wir testen. Obwohl es immer noch die gleichen 3 logischen Zweige gibt, die ich glaube, abgedeckt werden sollten. Ich denke, dass es die Statistik der bedingten Deckung heutzutage zu einem absoluten Vertrauensverlust macht.
Ist es sinnvoll, die bedingte Abdeckung für Java 8-Code zu messen? Gibt es andere Tools, die untersuchten Code erkennen?
quelle
getName
? Es scheint, dass wennuser
null ist, es "unbekannt" zurückgeben sollte. Wennuser
nicht null unduser.getName()
null ist, sollte "unknown" zurückgegeben werden. Wennuser
nicht null unduser.getName()
nicht null ist, sollte es das zurückgeben. Sie würden diese drei Fälle in einem Unit-Test testen, denngetName
darum geht es in dem Vertrag . Sie scheinen es rückwärts zu machen. Sie möchten die Zweige nicht sehen und die Tests nicht danach schreiben, Sie möchten Ihre Tests gemäß Ihrem Vertrag schreiben und sicherstellen, dass der Vertrag erfüllt ist. Dann haben Sie eine gute Abdeckung.Antworten:
Mir sind keine bekannt. Ich habe versucht, den Code, den Sie haben, über JaCoCo (auch bekannt als EclEmma) auszuführen, nur um sicherzugehen, aber es werden 0 Zweige in der
Optional
Version angezeigt . Ich kenne keine Methode zum Konfigurieren, um etwas anderes zu sagen. Wenn Sie es so konfigurieren, dass es auch JDK-Dateien enthält, werden theoretisch Verzweigungen angezeigtOptional
, aber ich halte es für dumm, mit der Überprüfung des JDK-Codes zu beginnen. Sie müssen nur davon ausgehen, dass es richtig ist.Ich denke, das Kernproblem ist jedoch, dass die zusätzlichen Zweige, die Sie vor Java 8 hatten, in gewisser Weise künstlich erstellte Zweige waren. Dass sie in Java 8 nicht mehr existieren, bedeutet nur, dass Sie jetzt das richtige Werkzeug für den Job haben (in diesem Fall
Optional
). In Code vor Java 8 mussten Sie zusätzliche Komponententests schreiben, damit Sie sicher sein können, dass sich jeder Codezweig in akzeptabler Weise verhält - und dies wird ein bisschen wichtiger in Codeabschnitten, die nicht so trivial sind wie derUser
/getName
Beispiel.Im Java 8-Code vertrauen Sie stattdessen auf das JDK, dass der Code ordnungsgemäß funktioniert. So wie es ist, sollten Sie diese
Optional
Zeile genauso behandeln wie Code Coverage Tools: 3 Zeilen mit 0 Zweigen. Dass es im Code unten noch andere Zeilen und Zweige gibt, haben Sie bisher noch nicht beachtet, aber es gab sie jedes Mal, wenn Sie so etwas wie einArrayList
oder verwendet habenHashMap
.quelle
if
undnull
immer noch ein Teil der Sprache ;-) Es ist immer noch möglich, Code auf alte Weise zu schreiben und zu übergebennull
Benutzer oder Benutzer mitnull
Namen. Ihre Tests sollten lediglich beweisen, dass der Vertrag erfüllt ist, unabhängig davon, wie die Methode implementiert ist. Der Punkt ist, dass es kein Tool gibt, mit dem Sie feststellen können, ob Sie den Vertrag vollständig getestet haben.Optional
man sie nicht mehr testen muss , wenn man der Funktionsweise (und verwandten Methoden) vertraut . Nicht so, wie Sie getestet habenif-else
: Jederif
war ein potenzielles Minenfeld.Optional
und ähnliche funktionale Redewendungen sind bereits kodiert und werden Sie garantiert nicht stören, sodass im Grunde genommen ein "Zweig" verschwunden ist.Optional
. Wie er sagte, sollten wir logischerweise immer noch testen, obgetName()
verschiedene mögliche Eingaben in der von uns beabsichtigten Weise verarbeitet werden, unabhängig von ihrer Implementierung. Es ist schwieriger, dies zu bestimmen, ohne dass die Codeabdeckungswerkzeuge wie vor JDK8 helfen.if-else
da jedes dieser Konstrukte vollständig ad-hoc ist. Im Gegensatz dazuOptional
,orElse
,map
usw, sind alle bereits getestet. Die Zweige "verschwinden", wenn Sie mächtigere Redewendungen verwenden.