Wie weit nimmst du Code Coverage? [geschlossen]

8

Ich benutze seit kurzem Code-Coverage-Tools (insbesondere Emma und EclEmma), und mir gefällt die Ansicht, dass es mir die Vollständigkeit meiner Unit-Tests gibt - und die Möglichkeit, zu sehen, welche Bereiche des Codes meine Einheit sind Tests treffen überhaupt nicht zu. Ich arbeite derzeit in einer Organisation, die nicht viel Komponententests durchführt, und ich habe vor, wirklich alle dazu zu bringen, Komponententests, Code-Coverage und TDD zu übernehmen und die Organisation hoffentlich zu konvertieren.

Ein Problem, mit dem ich mich bei diesem Thema nicht auskenne, ist genau, wie weit ich meinen Code abdecken sollte. Zum Beispiel, wenn ich eine Klasse wie diese habe:

%Vor%

Ich habe einige einfache Unit-Tests geschrieben, um sicherzustellen, dass equals() korrekt funktioniert, dass getValue() das zurückgibt, was ich erwartet habe usw. Aber dank der visuellen Natur von EclEmma erscheint die hashcode() -Methode als leuchtend rot für "nicht getestet".

Lohnt es sich überhaupt, in diesem Beispiel hashCode() zu testen, wenn man bedenkt, wie einfach die Implementierung ist? Ich habe das Gefühl, ich würde einen Komponententest für diese Methode hinzufügen, um die Codeabdeckung in% zu erhöhen und das grelle rote Highlight, das EclEmma diesen Zeilen hinzufügt, loszuwerden.

Vielleicht bin ich neurotisch und OCD-artig, aber ich finde, dass etwas wie EclEmma es so einfach macht zu sehen, was ungeprüft ist - das Plugin hebt den Quellcode in Rot hervor und bedeckt Code in Grün - macht wirklich Ich möchte pushen, um so viele Klassen 100% grün zu bekommen, wie ich kann - auch wenn es keinen großen Vorteil bringt.

    
matt b 31.10.2008, 14:01
quelle

8 Antworten

8

Ich benutze Code Coverage, um mir Hinweise auf Orte zu geben, an denen ich unvollständige Tests durchführen kann. Zum Beispiel kann ich einen Test für eine bestimmte Funktionalität schreiben und dann den Code entwickeln, der diese Funktionalität erfüllt, aber dabei Code schreiben, der mehr tut, als er eigentlich sollte - sagen wir, er könnte in einem anderen Fall eine Ausnahme abfangen dass der Test nicht funktioniert. Wenn ich den Coverage-Analyzer verwende, kann ich sehen, dass ich Code eingeführt habe, der keinen zugehörigen Test enthält. Es hilft mir zu wissen, wenn ich nicht genug Tests geschrieben habe.

Auf der anderen Seite kann die Coverage-Analyse zu falscher Sicherheit führen. Die vollständige Abdeckung Ihres Codes bedeutet nicht, dass Sie genügend Tests haben. Sie müssen über Tests nachdenken, was der Code tun soll und Tests schreiben, um sicherzustellen, dass es das tut. Vorzugsweise zuerst den Test schreiben. Nur weil Ihr Code vollständig abgedeckt ist, bedeutet das nicht, dass der Code das tut, was er tun soll.

In Ihrem Beispiel hätte ich den Test für hashCode geschrieben, um zu definieren, was die Funktionalität der Methode macht, bevor ich den Code geschrieben habe. Daher hätte ich es abgedeckt. Das bedeutet nicht, dass ich immer 100% Deckung habe. Ich bin nicht übereifrig, zum Beispiel Tests für einfache Accessoren zu schreiben. Ich kann auch nicht Methoden von der Elternklasse testen, wo ich von einem Framework erben, da ich nicht das Bedürfnis habe, den Code anderer Leute zu testen.

    
tvanfosson 31.10.2008, 14:06
quelle
6

Ich denke, es lohnt sich, eine Bibliothek zu verwenden, in der Sie bestimmte Aussagen ignorieren können. Zum Beispiel, wenn Sie eine Menge haben:

%Vor%

Dies ist nützlich, wenn Sie die Abdeckungsberechnungen für diese Linientypen deaktivieren können. Es kann auch (wohl) sinnvoll sein, Coverage-Berechnungen für triviale Getter und Setter zu deaktivieren (solche, die einfach eine Member-Variable ohne weitere Prüfungen oder Nebeneffekte setzen oder zurückgeben). Ich denke jedoch, dass, wenn Sie Equals und Hashcode überschrieben haben, diese getestet werden sollten. Sie haben nicht-triviale Funktionalität hinzugefügt, und es sollte getestet werden.

Nur um klar zu sein, der Grund, warum ich die obigen Situationen von der Berichterstattung ausgeschlossen sein sollte, ist:

  • Das Testen dieser Funktionalität ist nicht in Ordnung. Sie sollten Ihre gesamte Testsuite nicht fünf Mal durchlaufen müssen, wobei die Protokollierungsbibliothek auf jede Protokollierungsstufe eingestellt sein muss, um sicherzustellen, dass alle Ihre Anweisungen erfüllt werden.
  • Wenn Sie das oben genannte tun würden, würde es Ihre Berichterstattung in die andere Richtung verzerren. Wenn 90% Ihrer Zweige if(log.isDebugEnabled()) sind, und Sie alle, aber keine anderen Zweige testen, sieht es so aus, als hätten Sie 90% Zweigabdeckung (gut), während Sie in Wirklichkeit 0% nicht-triviale Zweigabdeckung haben (schlecht !!).
Chris Marasti-Georg 31.10.2008 14:07
quelle
4

Es gibt einen Unterschied zwischen Codeabdeckung und Testabdeckung. Sie sollten versuchen, sicherzustellen, dass Ihr Code angemessen getestet wird, anstatt eine 100% ige Codeabdeckung zu haben.

Betrachten Sie den folgenden Code:

%Vor%

Wenn Sie einen Test mit einem Wert von 1,0 ausgeführt haben, erhalten Sie bei allen Durchläufen 100% Codeabdeckung (Zweig und Anweisung). Der Code hat offensichtlich einen Defekt.

Das Messen der Testabdeckung ist schwieriger und eines, das von einem besseren Entwickler und Tester kommt.

Speziell in Bezug auf hashCode würde ein Gelehrter sagen, dass Sie einen separaten Einheitentest für diese Methode haben sollten. Ich persönlich würde sicherstellen, dass es in mindestens einem Unit-Integration Test enthalten ist und würde nicht jeden Accessor / Modifier direkt testen. Die Rendite Ihrer Investition ist oft zu gering, um den Aufwand zu rechtfertigen. Dies setzt natürlich voraus, dass Sie einen Komponententest haben, der sicherstellt, dass Sie den korrekten Hash-Code erzeugen.

    
Ryan Boucher 31.10.2008 14:32
quelle
3

Das Erreichen einer 100% igen Codeabdeckung mit aussagekräftigen Tests ist den Anstieg nicht wert, und wie bereits erwähnt, bedeutet 100% Code Coverage nicht unbedingt, dass alle möglichen Bedingungen in der Anwendung erfüllt wurden getestet.

Wie beim Testen von equals , hashCode und einigen anderen vertragsbasierten Schnittstellen, wie Comparable und Serializable , schließe ich diese Tests ein. Es ist wichtig, dass der equals/hashCode Vertrag korrekt implementiert wird, ebenso mit equals/Comparable .

Siehe JUnit-Addons , insbesondere

Ken Gentle 31.10.2008 14:37
quelle
2

Es mag jetzt nicht zu kompliziert sein, aber eine einfache Überprüfung, um zu überprüfen, dass es immer noch wie erwartet funktioniert, kann später sehr nützlich sein, wenn die Methode modifiziert wird.

Da der Check wirklich einfach zu schreiben sein sollte, warum nicht? Es hilft den Statistiken und hilft Ihnen auch später, falls es kaputt geht.

Auch für TDD möchten Sie 100% Abdeckung, denn dann können Sie sicher sein (oder sehr nahe daran), dass Sie nichts brechen, wenn Sie umgestalten.

    
chills42 31.10.2008 14:06
quelle
1

Ein anderer Programmierer steckte wie ich in altem Java1.4;)

Wie bereits in meinem previous Antwort , Code abgedeckt ist nicht Code-getestet. Und die Schlussfolgerung war: ab einem bestimmten Punkt ist die einzige Möglichkeit, die Codeabdeckung zu verbessern, ... Code zu löschen!

Nun ist es in Bezug auf hashCode interessant, dass es in einem Einheitentestentwurf behandelt wird, um zu prüfen, ob der erwartete sortierte Mechanismus respektiert wird (und nicht um eine weitere Funktion abzudecken).

    
VonC 31.10.2008 14:12
quelle
0

Wie ich schon an anderer Stelle gesagt habe, ist eine niedrige Codeabdeckung ein Problem, aber eine hohe Codeabdeckung bedeutet nicht, dass Sie reines Gold schreiben.

Wenn Ihnen die Code-Abdeckung nicht wichtig wäre, würde ich vorschlagen, dass Sie Tests für equals() und getValue() benötigen - abhängig davon, wie und wo hashCode() verwendet wird (sorry, ich ' m ein C # -Entwickler), dann möchten Sie dies testen.

Der wichtigste Teil ist, dass Ihre Tests Ihnen das Vertrauen geben, dass Sie den richtigen Code geschrieben haben und dass der Code wie erwartet funktioniert.

    
David Kemp 31.10.2008 14:07
quelle
0

In diesem speziellen Fall würde ich sagen, dass Sie, da Sie die equals-Methode testen, auch testen können, ob gleiche Objekte gleiche hashcodes haben: Fügen Sie einfach einen zusätzlichen Test zu allen Fällen hinzu, in denen equals wahr erwartet wird .

Das gibt Ihnen Code-Coverage und darüber hinaus gibt es Ihnen ein gewisses Vertrauen, dass hashCode seinen Vertrag tatsächlich erfüllt: -)

Es lohnt sich nur am Rande, da Sie der hashCode-Methode von String offensichtlich vertrauen können und Sie nicht erwarten, diese Klasse jemals zu ändern. Aber wenn Sie genug von Ihrer equals-Methode genug haben, um es überhaupt zu testen, dann sollten Sie misstrauisch genug sein, um zu testen, ob es und hashCode konsistent bleiben. Und Sie sollten immer misstrauisch gegenüber Annahmen sein, dass Sie sich in Zukunft nicht mit dem, was Sie bisher gemacht haben, herumschlagen wollen. Zum Beispiel, wenn jemand kommt und entscheidet, durch das Hinzufügen einer Zeiger-Gleichheitsprüfung zu "optimieren", dann können Sie genauso gut eine komplette Reihe von Tests haben, damit sie ihren modifizierten Code gegen ausführen können. Andernfalls werden sie Zeit mit der gleichen Sorge verschwenden, die Sie getan haben - ist es in Ordnung, dass ich keine Codeabdeckung habe?

    
Steve Jessop 31.10.2008 16:20
quelle

Tags und Links