Wie teste ich die Tests?


53

Wir testen unseren Code, um ihn korrekter zu machen (tatsächlich ist es weniger wahrscheinlich, dass er falsch ist ). Die Tests sind jedoch auch Code - sie können auch Fehler enthalten. Und wenn Ihre Tests fehlerhaft sind, verbessern sie Ihren Code kaum.

Ich kann mir drei mögliche Arten von Fehlern in Tests vorstellen:

  1. Logische Fehler, wenn der Programmierer die vorliegende Aufgabe missverstanden hat und die Tests das tun, was er für richtig hielt, was falsch ist.

  2. Fehler im zugrunde liegenden Testframework (z. B. eine undichte spöttische Abstraktion);

  3. Fehler in den Tests: Der Test macht etwas anders als der Programmierer denkt, dass es ist.

Es scheint unmöglich zu sein, Fehler vom Typ (1) zu verhindern (es sei denn, der Programmierer wird nur ... schlauer). (2) und (3) können jedoch handhabbar sein. Wie gehen Sie mit solchen Fehlern um? Haben Sie spezielle Strategien, um sie zu vermeiden? Schreiben Sie zum Beispiel einige spezielle "leere" Tests, die nur die Voraussetzungen des Testautors überprüfen? Wie gehen Sie beim Debuggen eines fehlerhaften Testfalls vor?


3
Jedes Einführungsstück, das ich über das Verspotten gelesen habe, scheint dieses Problem zu treffen. Sobald Sie anfangen, Dinge zu verspotten, scheinen die Tests immer komplizierter zu sein als der Code, den sie testen. Offensichtlich ist dies beim Testen von Code aus der realen Welt weniger wahrscheinlich, aber es ist ziemlich entmutigend, wenn Sie versuchen zu lernen.
Carson63000

@ Carson63000 Wenn es ein einfacher Test ist, der etwas mit einem getesteten Mock testet , ist die Komplexität aufgeteilt und unter Kontrolle (glaube ich).
mlvljr

13
Aber wie testet man dann die Testtests?
ocodo

+1. Punkt 1 könnte ein Anforderungsfehler sein. Kann nur durch Überprüfung der Anforderungen verhindert werden. Wahrscheinlich aus den Händen des Programmierers, es sei denn, sie sind auch der Anforderungsanalyst
MarkJ

@ocodo: Genauso wie du die Watchers beobachtest. :)
Greg Burghardt

Antworten:


18

Die Tests sind bereits getestet. Tests sind von Natur aus vor Fehlern geschützt, da beim Testen nur Unterschiede zwischen Code und unseren Erwartungen festgestellt werden. Bei Problemen haben wir einen Fehler. Der Fehler könnte im Code oder mit der gleichen Wahrscheinlichkeit in Tests liegen.

  1. Es gibt einige Techniken, die Sie daran hindern, denselben Fehler sowohl im Code als auch in den Tests hinzuzufügen:

    1. Der Kunde sollte eine andere Person sein als der Implementierer.
    2. Schreiben Sie zuerst die Tests und dann den Code (wie in Test Driven Development).
  2. Sie müssen die zugrunde liegende Plattform nicht testen. Bei den Tests wird nicht nur der von Ihnen geschriebene Code ausgeführt, sondern auch der Code von der Plattform aus. Während Sie nicht unbedingt Fehler in der Testplattform abfangen möchten, ist es sehr schwierig, Code und Tests zu schreiben, die immer einen Fehler in der Plattform verbergen, mit anderen Worten, es ist sehr schwierig, einen systematischen Fehler in Ihren Tests / Codes und zu finden in der Plattform und die Wahrscheinlichkeit wird mit jedem Test, den Sie erstellen, gesenkt. Selbst wenn Sie dies versuchen würden, hätten Sie eine sehr schwere Aufgabe.

  3. Sie könnten Fehler in Tests haben, aber normalerweise können diese leicht abgefangen werden, da die Tests durch den entwickelten Code getestet werden. Zwischen dem Code und den Tests gibt es ein Feedback zur Selbstdurchsetzung. Beide sagen voraus, wie sich ein bestimmter Aufruf einer Schnittstelle verhalten soll. Wenn die Antwort anders ist, müssen Sie keinen Fehler im Code haben. Sie könnten auch einen Fehler im Test haben.


Sehr nette Antwort. Ich mag die Idee einer sich selbst verstärkenden Schleife zwischen den Tests und dem Code und die Beobachtung, dass es schwierig sein würde, Tests zu schreiben, die Fehler in der zugrunde liegenden Plattform konsistent verbergen.
Ryszard Szopa

Dies verhindert nicht, dass Tests erstellt werden, die auf fehlerhaften Annahmen darüber basieren, was der eigentliche Code tun soll. Dies kann dazu führen, dass sehr böse Fehler während des Tests nicht entdeckt werden. Die einzige Möglichkeit, dies zu verhindern, besteht darin, die Tests von einem Dritten schreiben zu lassen, der keinerlei Beziehung zu der Organisation hat, die den eigentlichen Code schreibt, sodass sie nicht das gegenseitige Denken bei der Interpretation der Anforderungsdokumente "verfälschen" können.
Jwenting

24

Versuchen Sie, die einzelnen Tests so kurz wie möglich zu halten.

Dies sollte die Wahrscheinlichkeit verringern, dass ein Fehler auftritt. Selbst wenn Sie es schaffen, eine zu erstellen, ist es einfacher zu finden. Unit-Tests sollten klein und spezifisch sein und eine geringe Fehler- und Abweichungstoleranz aufweisen.

Am Ende ist es wahrscheinlich nur eine Frage der Erfahrung. Je mehr Tests du schreibst, desto besser wirst du, desto geringer ist die Wahrscheinlichkeit, dass du beschissene Tests machst.


3
Was ist, wenn die Tests etwas kompliziertes Setup erfordern? Manchmal sind solche Dinge nicht unter Ihrer Kontrolle.
Ryszard Szopa

Nun, ich vermute, die komplizierten Einstellungen sind "Ausgangsbedingungen" der Tests. Wenn dies fehlschlägt, sollten alle Ihre Tests fehlschlagen. Tatsächlich arbeite ich gerade an einem solchen Projekt, und Leute, die noch nie Unit-Tests verwendet haben, fragten ständig das Gleiche. Bis wir erklärten, was Unit-Tests wirklich sind Komplexität des Projekts.
Dr. Hannibal Lecter

Was ist der beste Weg, um zu überprüfen, ob diese "Ausgangsbedingung" erfüllt ist, ist genau der Punkt meiner Frage. Schreiben Sie dafür einen separaten Test? Oder nehmen Sie einfach an, dass die Tests abbrechen, wenn diese Bedingung nicht erfüllt ist? Was ist mit der Situation, in der das Setup nicht "katastrophal" schlecht ist, sondern nur leicht abweicht?
Ryszard Szopa

2
Ihre Tests sollten scheitern, wenn die Ausgangsbedingungen nicht stimmen. Das ist der springende Punkt. Im Status Aerwarten Sie das Ergebnis B. Wenn Sie keinen Status haben A, sollte ein Test fehlschlagen. An diesem Punkt können Sie untersuchen, warum es fehlgeschlagen ist, schlechte Anfangsbedingungen oder ein schlechter Test, aber es sollte in beiden Fällen fehlschlagen. Auch wenn es, wie Sie sagen, „etwas aus“ (dh "A" => "B", "a" => "b"aber nie "a" => "B"oder Ihr Test ist schlecht).
Dr. Hannibal Lecter

19

Eine Taktik besteht darin, den Test vor dem Code zu schreiben, der getestet wird, und sicherzustellen, dass der Test zuerst aus dem richtigen Grund fehlschlägt. Wenn Sie TDD verwenden , sollten Sie mindestens diese Teststufe erhalten.

Eine umfassendere Methode zum Testen der Qualität einer Testsuite ist die Verwendung von Mutationstests .


2
Und dass dein Test aus dem richtigen Grund fehlschlägt .
Frank Shearar

@Frank - Ja. Ich werde das zur Antwort hinzufügen.
Don Roby

Und Sie fügen einen neuen Test für das zu testende neue Verhalten hinzu. Fügen Sie keine vorhandenen Tests hinzu.
Huperniketes

@ DonRoby, Haben Sie Mutationstests in der Praxis für nützlich befunden? Welche Mängel haben Sie in Ihren Testfällen dabei festgestellt?
Dzieciou

4

Für # 1 und # 3: Unit-Tests sollten keine Logik enthalten. Wenn Sie dies tun, testen Sie wahrscheinlich mehr als eine Sache in Ihrem Unit-Test. Eine bewährte Methode für Unit-Tests besteht darin, nur einen Test pro Unit-Test durchzuführen.

In diesem Video von Roy Osherove erfahren Sie, wie Sie Komponententests gut schreiben können.


ad # 3 - Ich stimme zu, dass die Tests so einfach wie möglich sein und keine Logik enthalten sollten. Denken Sie jedoch an die Einrichtungsphase des Tests, wenn Sie die Objekte erstellen, die benötigt werden. Sie können leicht falsche Objekte erstellen. Dies ist die Art von Problemen, über die ich nachdenke.
Ryszard Szopa

Wenn Sie "leicht falsche Objekte" sagen, ist der Objektstatus nicht korrekt oder das tatsächliche Design des Objekts nicht korrekt? Für den Objektstatus könnten Sie wahrscheinlich Tests schreiben, um die Gültigkeit zu überprüfen. Wenn das Design falsch ist, sollte der Test fehlschlagen.
Piers Myers

3

In Bezug auf # 1 - Ich denke, es ist eine gute Idee, eine Paarung / Code-Überprüfung für diese Seite der Dinge durchzuführen. Es ist leicht, Voraussetzun- gen zu treffen oder Fehler zu machen, aber wenn Sie erklären müssen, was Ihr Test tut, worauf es ankommt, werden Sie eher aufhorchen, wenn Sie auf das falsche Ziel zielen.


2

Es muss einen Punkt geben, an dem man aufhören sollte, einen Unit-Test durchzuführen. Sollte wissen, wann die Grenze gezogen werden muss. Sollen wir Testfälle schreiben, um Testfälle zu testen? Was ist mit den neuen Testfällen, die für Testfälle geschrieben wurden? Wie werden wir sie testen?

if (0 > printf("Hello, world\n")) {
  printf("Printing \"Hello, world\" failed\n");
}

Bearbeiten: Aktualisiert mit Erläuterung, wie durch Kommentar vorgeschlagen.


-1 Was? Dies scheint keine Relevanz zu haben.
Alternative

2
Es muss einen Punkt geben, an dem man aufhören sollte, einen Unit-Test durchzuführen. Sollte wissen, wann die Grenze gezogen werden muss. Sollen wir Testfälle schreiben, um Testfälle zu testen? Was ist mit den neuen Testfällen, die für Testfälle geschrieben wurden? Wie werden wir sie testen?
aufather

2
Prozess Gehirn erhöht EInfiniteRecursion beim Versuch , Ihre Aussage zu extrapolieren ...
Mason Wheeler

Ersetzen Sie Ihre Antwort durch Ihren Kommentar und Sie erhalten eine +1
Notiz für sich selbst - denken Sie an einen Namen

3
Um ehrlich zu sein, ist Ihr Beispiel ein Strohmann. Sie testen das Subsystem printf () in einer C-Bibliothek, nicht das eigentliche Programm, das printf () aufruft. Ich stimme jedoch zu, dass man irgendwann das rekursive Testen von Tests unterbrechen muss.
Tim Post

2

Hallo.
Sie müssen sich bewerben:

  • Ihr Produkt
  • Ihr Test für dieses Produkt.

Wenn Sie Tests für Ihr Produkt ausführen, sind Sie eigentlich nicht am Test selbst interessiert, sondern an der Interaktion zwischen Ihrem Produkt und Ihren Tests. Wenn der Test fehlschlägt, bedeutet dies nicht, dass die Anwendung einen Fehler aufweist. Es heißt, dass die Interaktion zwischen Produkt und Test nicht erfolgreich war . Jetzt ist es Ihre Aufgabe, festzustellen, was schief gelaufen ist. Es kann entweder sein:

  • Anwendung verhält sich nicht wie erwartet (diese Erwartung kommt in Ihrem Test zum Ausdruck)
  • Anwendung verhält sich korrekt, Sie haben dieses Verhalten nur nicht korrekt dokumentiert (in Ihren Tests)

Für mich sind fehlgeschlagene Tests keine einfache Rückmeldung, dass dies und das falsch ist . Es ist ein Anzeichen dafür, dass es eine Inkonsistenz gibt, und ich muss beide untersuchen, um zu überprüfen, ob ein Fehler aufgetreten ist. Letztendlich bin ich dafür verantwortlich, die Richtigkeit der Anwendung zu überprüfen. Tests sind nur ein Hilfsmittel, um Bereiche hervorzuheben, die es wert sind, überprüft zu werden.

Tests überprüfen nur einige Teile der Anwendung. Ich teste die Anwendung, ich teste die Tests.


2

Tests sollten nicht "schlau" genug sein, um Fehler zu beherbergen.

Der Code, den Sie schreiben, implementiert eine Reihe von Spezifikationen. (Wenn X, dann Y, außer Z, in welchem ​​Fall Q, usw. usw.). Bei dem Test sollte lediglich versucht werden, festzustellen, ob X wirklich Y ist, es sei denn, Z ist in diesem Fall Q. Dies bedeutet, dass bei einem Test nur X festgelegt und Y überprüft werden muss.

Aber das deckt nicht alle Fälle ab, und Sie hätten Recht. Wenn Sie den Test jedoch "schlau" machen, um zu wissen, dass X nur von Y, wenn nicht von Z, verwendet werden sollte, implementieren Sie die Geschäftslogik im Test im Grunde neu. Dies ist aus Gründen problematisch, auf die wir weiter unten näher eingehen werden. Sie sollten die Codeabdeckung nicht verbessern, indem Sie Ihren ersten Test "schlauer" machen. Stattdessen sollten Sie einen zweiten dummen Test hinzufügen, der X und Z setzt und Q überprüft. Auf diese Weise haben Sie zwei Tests, einen, der den allgemeinen Fall abdeckt ( manchmal auch als Happy Path bezeichnet) und einen, der den Edge-Fall als separaten Test abdeckt.

Dafür gibt es eine Reihe von Gründen. In erster Linie, wie können Sie feststellen, ob ein fehlgeschlagener Test auf einen Fehler in der Geschäftslogik oder auf einen Fehler in den Tests zurückzuführen ist? Die Antwort ist natürlich, dass die Tests, wenn sie so einfach wie möglich sind, höchstwahrscheinlich keine Fehler enthalten. Wenn Sie glauben, dass Ihre Tests getestet werden müssen, testen Sie falsch .

Andere Gründe sind, dass Sie nur den Aufwand replizieren (wie bereits erwähnt, wenn Sie einen Test schreiben, der intelligent genug ist, um alle Möglichkeiten in einem einzigen Test auszuüben, wird im Grunde die Geschäftslogik repliziert, die Sie zu testen versuchen), wenn sich die Anforderungen ändern Dann sollten die Tests leicht zu ändern sein, um die neuen Anforderungen widerzuspiegeln. Tests dienen als eine Art Dokumentation (sie sind eine formale Art zu sagen, wie die Spezifikation des zu testenden Geräts lautet) und so weiter.

TL: DR: Wenn Ihre Tests getestet werden müssen, machen Sie es falsch. Schreibe blöde Tests .


0

Keine Antwort (ich habe keine Berechtigung zum Kommentieren), habe mich jedoch gefragt, ob Sie andere Gründe für die Entwicklung von Testfällen vergessen haben
. Automatisierte Testsuiten helfen Ihnen, Probleme vor der Integration früher zu finden. Die Änderungen an den Anforderungen sind relativ einfach zu testen, da die Änderungen neuer werden können, die Version älterer Testfälle geändert wird und ältere Fälle weiterhin Fehler erkennen.


0

Kurze Antwort: Der Produktionscode testet die Tests .

Vergleichen Sie dies mit dem in der Wirtschaft verwendeten Kredit- / Debitmodell . Die Mechanik ist sehr einfach - Wenn die Gutschrift von der Abbuchung abweicht, stimmt etwas nicht.

Gleiches gilt für Komponententests - Wenn ein Test fehlschlägt, bedeutet dies, dass etwas nicht stimmt. Es könnte der Produktionscode sein, aber es könnte auch der Testcode sein! Dieser letzte Teil ist wichtig.

Beachten Sie, dass Ihre Typ (1) -Fehler bei Unit-Tests nicht gefunden werden können. Um diese Art von Fehlern zu vermeiden, benötigen Sie andere Tools.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.