Frage

Wenn ich einen Code habe, der 80% Testabdeckung hat (alle Tests bestehen), ist es fair zu sagen, dass er von höherer Qualität als Code ohne Testabdeckung ist?

Oder ist es fair zu sagen, dass es wartbarer ist?

War es hilfreich?

Lösung

In einem strengen Sinne ist es nicht fair, irgendwelche Ansprüche zu gründen, bis die Qualität der Testsuite festgelegt ist. Das Bestehen von 100% der Tests ist nicht sinnvoll, wenn die meisten Tests trivial oder sich wiederholt.

Die Frage ist: Haben in der Geschichte des Projekts einer dieser Tests Fehler entdeckt? Das Ziel eines Tests ist es, Fehler zu finden. Und wenn sie es nicht taten, scheiterten sie als Tests. Anstatt die Codequalität zu verbessern, geben sie Ihnen möglicherweise nur ein falsches Sicherheitsgefühl.

Um Ihre Testdesigns zu verbessern, können Sie (1) Whitebox -Techniken, (2) Blackbox -Techniken und (3) Mutationstests verwenden.

(1) Hier sind einige gute Whitebox -Techniken, die Sie für Ihre Testdesigns anwenden können. Ein WhiteBox -Test wird mit spezifischem Quellcode konstruiert. Ein wichtiger Aspekt des Whitebox -Tests ist die Codeabdeckung:

  • Wird jede Funktion aufgerufen? [Funktionsabdeckung
  • Wird jede Aussage ausgeführt? [Erklärung der Berichterstattung- Sowohl funktionale Berichterstattung als auch Anweisungsberichterstattung sind sehr einfach, aber besser als nichts
  • Für jede Entscheidung (wie if oder while), haben Sie einen Test, der es dazu zwingt, wahr zu sein, und andere, die ihn dazu zwingen, falsch zu sein? [Entscheidungsberichterstattung
  • Für jede Bedingung, die eine Konjunktion ist (verwendet &&) oder disjunktion (verwendet ||), hat jede Unterexpression einen Test, bei dem er wahr/falsch ist? [Bedingungsabdeckung
  • Schleifenabdeckung: Haben Sie einen Test, der 0 Iterationen, 1 Iteration, 2 Iterationen erzwingt?
  • Ist jeweils break Von einer Schleife abgedeckt?

(2) Blackbox -Techniken werden verwendet, wenn die Anforderungen verfügbar sind, der Code selbst jedoch nicht. Diese können zu hochwertigen Tests führen:

  • Decken Ihre Blackbox -Tests mehrere Testziele ab? Sie möchten, dass Ihre Tests "fett" sind: Sie testen nicht nur Feature X, sondern testen auch Y und Z. Die Interaktion verschiedener Funktionen ist eine großartige Möglichkeit, Fehler zu finden.
  • Der einzige Fall, den Sie keine "Fett" -Tests wünschen, ist, wenn Sie eine Fehlerbedingung testen. Zum Beispiel Testen auf ungültige Benutzereingaben. Wenn Sie versucht haben, mehrere ungültige Eingabe -Testziele zu erreichen (z. B. eine ungültige Postleitzahl und eine ungültige Straßenadresse), ist es wahrscheinlich, dass ein Fall den anderen maskiert.
  • Betrachten Sie die Eingangstypen und bilden Sie eine "Äquivalenzklasse" für die Arten von Eingängen. Wenn Ihre Code beispielsweise testet, um festzustellen, ob ein Dreieck gleichseitig ist, findet der Test, bei dem ein Dreieck mit Seiten (1, 1, 1) verwendet wird, wahrscheinlich die gleichen Fehler wie die Testdaten (2, 2, 2) und (3, 3, 3) wird finden. Es ist besser, Ihre Zeit damit zu verbringen, an andere Eingabenklassen zu denken. Wenn Ihr Programm beispielsweise Steuern erledigt, möchten Sie einen Test für jede Steuerklasse. [Dies nennt man Äquivalenzaufteilung.
  • Spezielle Fälle sind häufig mit Mängel verbunden. Ihre Testdaten sollten auch Grenzwerte aufweisen, wie z. B. die oben oder unter den Kanten einer Äquivalenzaufgabe. Wenn Sie beispielsweise einen Sortieralgorithmus testen, möchten Sie beispielsweise mit einem leeren Array, einem einzelnen Elementarray, einem Array mit zwei Elementen und einem sehr großen Array testen. Sie sollten Grenzfälle nicht nur für die Eingabe, sondern auch für die Ausgabe in Betracht ziehen. [Dies ist die Analyse der Randgrenze.
  • Eine andere Technik ist "Fehler beim Erraten". Haben Sie das Gefühl, wenn Sie eine spezielle Kombination ausprobieren, die Sie zum Brechen bringen können? Dann versuchen Sie es einfach! Denken Sie daran: Ihr Ziel ist es, Fehler zu finden, um nicht zu bestätigen, dass das Programm gültig ist. Einige Leute haben das Händchen für Fehler beim Erraten.

(3) Nehmen wir schließlich an, Sie haben bereits viele schöne Tests für WhiteBox -Abdeckung und angewendete Blackbox -Techniken. Was kannst du sonst noch tun? Es ist Zeit zu Testen Sie Ihre Tests. Eine Technik, die Sie verwenden können, sind Mutationstests.

Unter Mutationstests stellen Sie eine Änderung an (eine Kopie Ihres Programms) vor, in der Hoffnung, einen Fehler zu erstellen. Eine Mutation könnte sein:

Ändern Sie eine Referenz einer Variablen in eine andere Variable; Fügen Sie die Funktion ABS () ein; Weniger als größere als größere Wechsel wechseln; Eine Anweisung löschen; Ersetzen Sie eine Variable durch eine Konstante; Eine übergeordnete Methode löschen; Löschen Sie einen Verweis auf eine Supermethode; Argumentationsreihenfolge ändern

Erstellen Sie mehrere Dutzend Mutanten an verschiedenen Stellen in Ihrem Programm [das Programm muss noch kompilieren, um zu testen]. Wenn Ihre Tests diese Fehler nicht finden, müssen Sie jetzt einen Test schreiben, der den Fehler in der mutierten Version Ihres Programms finden kann. Sobald ein Test den Fehler findet, haben Sie die Mutante getötet und können einen anderen versuchen.


Nachtrag: Ich habe vergessen, diesen Effekt zu erwähnen: Bugs neigen dazu, sich zu gruppieren. Das bedeutet, dass je mehr Fehler Sie in einem Modul finden, desto höher ist die Wahrscheinlichkeit, dass Sie mehr Fehler finden. Wenn Sie also einen Test haben, der fehlschlägt (was heißt, ist der Test erfolgreich, da das Ziel darin besteht, Fehler zu finden), sollten Sie nicht nur den Fehler beheben, sondern Sie sollten auch mehr Tests für das Modul mit dem Modul schreiben Techniken oben.

Solange Sie Fehler in einer stetigen Geschwindigkeit finden, müssen die Testbemühungen fortgesetzt werden. Nur wenn die Geschwindigkeit neuer Fehler zurückgegangen ist, sollten Sie das Vertrauen haben, dass Sie gute Testbemühungen für diese Entwicklungsphase unternommen haben.

Andere Tipps

Nach einer Definition ist es besser gewartet, da jede Veränderung eher von den Tests erfasst wird.

Die Tatsache, dass Code die Unit -Tests bestehen, bedeutet jedoch nicht, dass er von größerer Qualität in Anspruch genommen wird. Der Code ist möglicherweise immer noch schlecht mit irrelevanten Kommentaren und unangemessenen Datenstrukturen formatiert, kann jedoch die Tests bestehen.

Ich weiß, welcher Code würde es vorziehen, um zu warten und zu erweitern.

Code mit absolut keine Tests können von extrem hoher Qualität, lesbar, schön und effizient (oder totaler Müll) sein. Nein, es ist nicht fair zu sagen, dass Code mit 80 % Testabdeckung von höherer Qualität ist als Code ohne Testabdeckung.

Es könnte fair sein zu sagen, dass Code 80 % mit bedecktem Code mit gut Tests ist wahrscheinlich von akzeptabler Qualität und wahrscheinlich relativ wartbar. Aber es garantiert wirklich wenig.

Ich würde es refaktoriger nennen. Refactoring wird extrem einfach, wenn Code mit vielen Tests abgedeckt wird.

Es wäre fair, es besser zu bezeichnen.

Ich würde mir über den wartbaren Teil zustimmen. Michael Feathers hat kürzlich ein Video von einem hervorragenden Vortrag von seinem Calling gepostet "Die tiefe Synergie zwischen Testbarkeit und gutem Design"In dem er dieses Thema diskutiert. In dem Vortrag sagt er, dass die Beziehung eine Möglichkeit ist, dh gut gestaltete Code ist prüfbar, aber Testable Code ist nicht unbedingt gut gestaltet.

Es ist erwähnenswert, dass das Video -Streaming im Video nicht großartig ist, daher lohnt es sich möglicherweise herunterzuladen, wenn Sie vollständig ansehen möchten.

Ich stelle mir diese Frage seit einiger Zeit in Bezug auf die "Bedingungsberichterstattung". Wie wäre es mit dieser Seite von atollic.com "Warum Code -Abdeckungsanalyse?"

Technisch gesehen findet die Codeabdeckungsanalyse Bereiche in Ihrem Programm, die nicht von Ihren Testfällen behandelt werden, sodass Sie zusätzliche Tests erstellen können, die ansonsten ungetestete Teile Ihres Programms abdecken. Es ist daher wichtig zu verstehen Die Codeabdeckung hilft Ihnen, die Qualität Ihrer Testverfahren zu verstehen, nicht die Qualität des Codes selbst.

Dies scheint hier sehr relevant zu sein. Wenn Sie einen Testfall -Satz haben, der es schafft, eine bestimmte Ebene an (Code oder auf andere Weise) zu erreichen, rufen Sie den zu testenden Code mit einem ziemlich umfassenden Satz von Eingabetwerten sehr wahrscheinlich an! Dies wird Ihnen nicht viel über den zu testenden Code erzählen (es sei denn, der Code bläst in die Luft oder erzeugt erkennbare Fehler), gibt jedoch Sie jedoch, sondern gibt es Ihnen, gibt es Ihnen jedoch Vertrauen in Ihren Testfallsatz.

In einem interessanten Neckerwürfel View-of-View-View, der Testcode wird jetzt vom zu testenden Code getestet!

Es gibt viele Möglichkeiten, um sicherzustellen, dass ein Programm das tut, was Sie beabsichtigen, und um sicherzustellen, dass Änderungen keine unbeabsichtigten Auswirkungen haben.

Tests ist eins. Die Vermeidung von Datenmutationen ist eine andere. So ist auch ein Typsystem. Oder formelle Überprüfung.

Obwohl ich damit einverstanden bin, dass Tests im Allgemeinen eine gute Sache sind, bedeutet ein bestimmter Prozentsatz der Tests möglicherweise nicht viel. Ich würde mich lieber auf etwas verlassen, das in Haskell ohne Tests geschrieben wurde, als auf eine gut getestete PHP -Bibliothek

Lizenziert unter: CC-BY-SA mit Zuschreibung
scroll top