Wie soll ich meinen TEST Code testen?

22

Eines der wenigen Dinge, denen sich die meisten Softwareentwickler einig sind, ist, dass Sie sich nicht darauf verlassen sollten, dass Code richtig funktioniert, es sei denn, Sie testen ihn. Wenn Sie es nicht testen, hat es möglicherweise versteckte Fehler, die Sie später nur noch mehr arbeiten lassen.

Ich verstehe, wie ich meinen normalen Code teste, aber wie soll ich meinen Testcode testen, um sicherzustellen, dass er Fehler effektiv findet und meldet, wenn sie vorhanden sind? Ich persönlich war dumm genug, fehlerhafte Testfälle zu schreiben, die bestanden hätten, wenn sie nicht bestanden hätten, und damit den Zweck meiner Tests überhaupt zunichte zu machen. Glücklicherweise habe ich die Fehler rechtzeitig gefunden und behoben, aber laut Test-Mantra scheint es, als ob keine Testsuite vollständig wäre, ohne eigene Tests, um sicherzustellen, dass sie funktionieren.

Mir scheint, der beste Weg, dies zu tun, besteht darin, sicherzustellen, dass der Test für fehlerhaften Code fehlschlägt. * Wenn ich 2 Minuten damit verbringe, dem Code abwechselnd Fehler hinzuzufügen und sicherzustellen, dass er fehlschlägt, sollte ich ein akzeptables Maß an Vertrauen haben Die Tests funktionieren. Dies bringt mich zu meiner zweiten Frage: Was sind gute Möglichkeiten, Fehler einzuführen, um sicherzustellen, dass sie von den Testfällen erfasst werden? Soll ich nur zufällig Anweisungen auskommentieren, sicherstellen, dass der falsche Zweig von a if-elseausgeführt wird, indem sein Zustand negiert wird, und die Ausführungsreihenfolge von Code mit Nebenwirkungen usw. ändern, bis ich zufrieden bin, dass meine Tests die meisten Ergebnisse erzielenhäufige Fehler? Wie validieren professionelle Entwickler, dass ihre Tests tatsächlich das tun, was sie tun sollen? Nehmen sie einfach an, dass die Tests funktionieren, oder nehmen sie sich auch die Zeit, sie zu testen? Wenn ja, wie testen sie die Tests?

Ich schlage nicht vor, dass die Leute so viel Zeit damit verbringen sollten, ihre Tests zu testen und dann die Tests auf ihre Tests zu testen, dass sie nie den tatsächlichen Code schreiben, aber ich habe dumm genug gehandelt, dass ich das Gefühl habe, ein bisschen davon profitieren zu können von "Meta-Testing", und war neugierig auf den besten Weg, dies zu tun. : D

* Ich könnte überprüfen, ob der Test bestanden wurde, wenn ich fehlerfreien Code teste, aber die Verwendung des Codes als Testspezifikation scheint ziemlich rückständig zu sein ...

Gordon Gustafson
quelle
Klingt so, als hätten Sie kein Vertrauen in Ihre Komponententests - höchstwahrscheinlich, weil Ihnen viel Erfahrung beim Schreiben von Tests fehlt? In diesem Fall wäre es unvernünftig, mehr Tests zu schreiben und ein anderes Ergebnis zu erwarten. Mach einfach weiter, was du tust, sei so gründlich wie möglich (teste auf Fehler und Erfolg) und bald werden sich deine Unit-Tests bezahlt machen - und dein Vertrauen in sie wird wachsen.
MattDavey
Mögliches Duplikat von Wie
gnat
Verwenden Sie Ihre tatsächlichen Werkzeuge besser, bevor Sie weitere Werkzeuge verwenden . Schreiben Sie weniger Tests, aber effizientere und besser geschriebene Tests. Sie können etwas nicht vertrauen, das Sie nicht verstehen.
Steve Chamaillard

Antworten:

16

Der Standardfluss für TDD ist:

  1. Schreiben Sie einen nicht bestandenen Test. (Rot)
  2. Nehmen Sie die kleinste Codeänderung vor, die zum Bestehen führt (grün)
  3. Refactor (Grün bleiben)

Der Test für Ihre Tests ist in diesem Fall Schritt 1 - Stellen Sie sicher, dass der Test fehlschlägt, bevor Sie Codeänderungen vornehmen.

Ein anderer Test, den ich mag, ist, ob Sie Code löschen und auf andere Weise neu implementieren können. Ihre Tests schlagen nach dem Löschen fehl, arbeiten jedoch mit einem anderen Algorithmus.

Wie bei allen Dingen gibt es kein Wundermittel. Das Vergessen, einen erforderlichen Test zu schreiben, ist für einen Entwickler genauso einfach wie das Vergessen, den Code zu schreiben. Zumindest wenn Sie beides tun, haben Sie doppelt so viele Möglichkeiten, Ihre Lücke zu schließen.

Bringer128
quelle
4
Doppelte Buchhaltung: Die Unit-Tests testen den Produktionscode und umgekehrt. Es gibt zwei verschiedene Möglichkeiten, um dasselbe Problem zu benennen. Wie in der doppelten Buchhaltung, wo Sie Ihre Transaktionen auf zwei verschiedene Arten erfassen und beide die gleichen Summen erhalten müssen.
EricSchaefer
Die Frage bezieht sich auf das Problem, wenn in Schritt 2 der Test grün angezeigt wird, obwohl der Code noch fehlerhaft ist. Einfaches Beispiel: Sie haben eine Funktion, die einen Zeiger auf ein nicht leeres Listenobjekt zurückgeben muss. Ihr Test testet, ob der Zeiger nullin Schritt 1 vorhanden ist und nicht. Sie nehmen die kleinste Codeänderung vor, die durch das Zurückgeben einer leeren Liste verursacht wird. Der Test ist jetzt "grün", weil Sie zwei Fehler haben.
Christian Hackl
@ChristianHackl in dieser Entwicklungsphase ist es eine perfekte Umsetzung! Sie müssen einen (oder mehrere) Tests hinzufügen, die zunächst fehlschlagen, um das erwartete Verhalten weiter zu spezifizieren. Anschließend implementieren Sie es und machen diese Tests grün.
Andy
@Andy: Möchten Sie näher erläutern, wie dies eine perfekte Implementierung ist, wenn ich sowohl im Code als auch im Test einen Fehler habe und einer mich davon abhält, den anderen zu bemerken? (Der Fehler im Code ist, dass eine leere Liste zurückgegeben wird, und der Fehler im Test ist, dass ich nach nullund nicht nach leer suche.)
Christian Hackl
@ChristianHackl du hast recht nach dem leeren Scheck. Das sollte in der Tat auch in einem Test gemacht werden. Wenn Sie Ihre Anforderungen Schritt für Schritt in Tests umsetzen, ist nur wenig Platz für Fehler. Außer wenn Sie sich nicht an die Spezifikation halten (wie das Übersehen eines nicht leeren Schecks).
Andy
9

Ein Ansatz ist das Testen von Mutationen mit einem Tool wie Jester :

Jester nimmt einige Änderungen an Ihrem Code vor, führt Ihre Tests aus, und wenn die Tests bestanden werden, zeigt Jester eine Meldung an, die besagt, was sich geändert hat

Parsifal
quelle
4

Tests für Tests? Geh nicht diesen Weg. Dann brauchst du wahrscheinlich Tests für Tests und dann Tests für Tests für Tests ... wo hörst du auf?

Der übliche Testablauf sieht folgendermaßen aus: Als Entwickler verbringen Sie die meiste Zeit mit den Punkten 1 bis 3:

  1. Code
  2. Unit-Tests
  3. Integrationstests
  4. System / Sonstiges automatisiert
  5. QA / Human Tester

Wenn ich 2 Minuten damit verbringe, abwechselnd Fehler zum Code hinzuzufügen (...)

Ihr Code wird irgendwann seine eigenen Fehler "wachsen" lassen. Verschwenden Sie keine Zeit damit, sie manuell einzuführen. Ganz zu schweigen davon, ist eine Sache, die Sie von vornherein kannten, wirklich ein Fehler? Es werden Käfer kommen, darüber würde ich mir keine Sorgen machen.

Soll ich Anweisungen nur zufällig auskommentieren, stelle sicher, dass der falsche Zweig eines if-else ausgeführt wird, indem seine Bedingung negiert wird (...)

Dies ist ein praktikabler Ansatz, um zu überprüfen, ob Sie tatsächlich testen, was Sie zu tun glauben. Ich denke nicht, dass es immer so gut ist, da es das gleiche Problem hat wie "Test für Test für Test ...".

Es ist auch gut, sich an den klassischen, pragmatischen Ratschlag eines Programmierers zu erinnern - Sie werden ihn nicht brauchen . Seien Sie agil, schreiben Sie Tests und Code für tatsächliche Fehler, anstatt für die hypothetischen Fehler, die möglicherweise auftreten oder nicht.

km
quelle
3
Ich mache mir keine Sorgen, dass mein Code seine eigenen Fehler verursacht. Ich mache mir Sorgen, dass meine Tests sie erkennen, wenn sie auftreten. Wenn meine Tests fehlerhaft sind, machen sie ihre Arbeit nicht und ich denke, dass ich eine bestimmte Klasse von Fehlern beseitigt habe, wenn sie tatsächlich noch existieren, was meine Arbeit nur erschwert, weil ich auf ungenaue Testergebnisse schaue (bestanden, wenn sie scheitern sollten).
Gordon Gustafson
@ CrazyJugglerDrummer: Ihre Tests werden nicht alle Bugs fangen, das ist sicher. Sie erfüllen diesen Zweck nicht - hier kommt die Qualitätssicherung ins Spiel. Wenn sie dies tun würden, wäre die Software fehlerfrei, es sei denn, der Quellcode ändert sich, was ich noch nie gesehen habe.
km
3

Durch die Konstruktion werden Funktionscode und Testcode gegeneinander getestet. Ein Problem bleibt bestehen: der Fall von Gleichtaktfehlern, wenn ein Fehler im Funktionscode durch einen Fehler im Testcode ausgeblendet wird. TDD ist gegen diesen Effekt nicht immun. Aus diesem Grund werden Tests in der Regel von verschiedenen Personen auf mehreren Ebenen durchgeführt, um diese Wahrscheinlichkeit zu verringern.

mouviciel
quelle
0

Sie testen Ihren Komponententest einmal, wenn Sie ihn im Debugger schreiben. Dann lässt du es in Ruhe und vergisst es. Hier gibt es kein Problem.

Bedenken Sie. Was ist der Zweck eines Komponententests? Sie werden benachrichtigt, wenn eine der zahlreichen Änderungen, die Sie an Ihrem Hauptprogramm vornehmen, versehentlich die Logik in diesem Programm ändert. Sie möchten das haben, weil Sie wissen, dass jede Änderung möglicherweise etwas kaputt macht. Genau aus diesem Grund gibt es kein Problem, wenn Sie Ihren Test nicht testen: Sie machen keinen Fehler mit Ihrem Test, bis Sie die Logik Ihres Programms absichtlich ändern (was es erforderlich machen würde, den Test erneut zu überprüfen und erneut zu testen) Es ist nicht wahrscheinlich, dass der Test versehentlich abbricht.

Martin Maat
quelle
-2

Es gibt einen Mutationstest , der die Eignung und Qualität des Tests bewertet und misst.

Wir können dies verwenden, um "den Test" selbst auszuwerten.

Kurz gesagt, wir können unseren Test (z. B. TestA) durch Testen auswerten. TestA kann den Unterschied zwischen dem Code und seinen Mutationscodes feststellen (sehr ähnlicher, aber geringfügig unterschiedlicher Code mit Originalcode).

Wenn TestA den Unterschied zwischen dem Code und seinen Mutationscodes nicht finden kann, bedeutet dies, dass TestA zu grobe Vorschriften hat, um den Originalcode zu testen.

Hühnchenjäger
quelle