Ich habe gerade mein College beendet und fange nächste Woche irgendwo an zu studieren. Wir haben Unit-Tests gesehen, aber wir haben sie nicht oft benutzt. und alle reden über sie, also dachte ich mir, ich sollte vielleicht welche machen.
Das Problem ist, ich weiß nicht, was ich testen soll. Soll ich den allgemeinen Fall testen? Der Randfall? Woher weiß ich, dass eine Funktion ausreichend abgedeckt ist?
Ich habe immer das schreckliche Gefühl, dass ein Test zwar beweisen wird, dass eine Funktion für einen bestimmten Fall funktioniert, es aber völlig nutzlos ist, zu beweisen, dass die Funktion funktioniert, Punkt.
Antworten:
Meine persönliche Philosophie war bisher:
quelle
Unter der Fülle von Antworten hat bisher niemand die Äquivalenzaufteilung und die Grenzwertanalyse angesprochen , wichtige Überlegungen bei der Beantwortung der vorliegenden Frage. Alle anderen Antworten sind zwar nützlich, aber qualitativ, aber es ist möglich - und vorzuziehen -, hier quantitativ zu sein. @fishtoaster enthält einige konkrete Richtlinien, die sich nur mit der Testquantifizierung befassen. Mit der Äquivalenzpartitionierung und der Grenzwertanalyse können wir jedoch bessere Ergebnisse erzielen.
Bei der Äquivalenzpartitionierung teilen Sie die Menge aller möglichen Eingaben basierend auf den erwarteten Ergebnissen in Gruppen auf. Jede Eingabe von einer Gruppe führt zu äquivalenten Ergebnissen. Daher werden solche Gruppen Äquivalenzklassen genannt . (Beachten Sie, dass äquivalente Ergebnisse nicht identische Ergebnisse bedeuten.)
Betrachten Sie als einfaches Beispiel ein Programm, das ASCII-Kleinbuchstaben in Großbuchstaben umwandeln soll. Andere Charaktere sollten einer Identitätsumwandlung unterzogen werden, dh unverändert bleiben. Hier ist eine mögliche Unterteilung in Äquivalenzklassen:
In der letzten Spalte wird die Anzahl der Testfälle angegeben, wenn Sie alle auflisten. Technisch gesehen würden Sie nach @ fishtoasters Regel 1 52 Testfälle einschließen - alle diese für die ersten beiden oben angegebenen Zeilen fallen unter den "allgemeinen Fall". @ fishtoasters Regel 2 würde auch einige oder alle der obigen Zeilen 3 und 4 hinzufügen. Beim Testen der Äquivalenzpartitionierung ist jedoch ein Testfall in jeder Äquivalenzklasse ausreichend. Wenn Sie "a" oder "g" oder "w" auswählen, testen Sie denselben Codepfad. Sie haben also insgesamt 4 Testfälle statt mehr als 52.
Die Grenzwertanalyse empfiehlt eine geringfügige Verfeinerung: Im Wesentlichen deutet dies darauf hin, dass nicht jedes Mitglied einer Äquivalenzklasse äquivalent ist. Das heißt, Werte an Grenzen sollten auch für sich genommen als eines Testfalls würdig angesehen werden. (Eine einfache Rechtfertigung dafür ist der berüchtigte Fehler , bei dem es sich um einen Fehler handelt !) Sie könnten also für jede Äquivalenzklasse 3 Testeingaben haben. Wenn ich mir die obige Eingabedomäne anschaue - und die ASCII-Werte einigermaßen kenne -, fallen mir möglicherweise folgende Testfall-Eingaben ein:
(Sobald Sie mehr als 3 Grenzwerte erhalten, die darauf hindeuten, dass Sie möglicherweise Ihre ursprünglichen Äquivalenzklassen-Abgrenzungen überdenken möchten, war dies jedoch so einfach, dass ich nicht zurückgegangen bin, um sie zu überarbeiten.) Daher bringt uns die Grenzwertanalyse auf den Punkt 17 Testfälle - mit einem hohen Vertrauen in die vollständige Abdeckung - verglichen mit 128 Testfällen, um umfassende Tests durchzuführen. (Ganz zu schweigen davon, dass die Kombinatorik vorschreibt, dass umfassende Tests für jede reale Anwendung einfach nicht durchführbar sind!)
quelle
Wahrscheinlich ist meine Meinung nicht allzu beliebt. Aber ich schlage vor, dass Sie mit Unit-Tests sparsam umgehen. Wenn Sie zu viele Komponententests haben, verbringen Sie die Hälfte Ihrer Zeit oder mehr damit, Tests zu verwalten, anstatt die eigentliche Codierung vorzunehmen.
Ich empfehle Ihnen, Tests für Dinge zu schreiben, bei denen Sie ein schlechtes Gefühl im Bauch haben oder für Dinge, die sehr wichtig und / oder elementar sind. IMHO-Komponententests sind kein Ersatz für gutes Engineering und defensive Codierung. Derzeit arbeite ich an einem Projekt, das mehr oder weniger unbrauchbar ist. Es ist wirklich stabil, aber ein Schmerz für die Umgestaltung. Tatsächlich hat niemand diesen Code in einem Jahr berührt und der Software-Stack, auf dem er basiert, ist 4 Jahre alt. Warum? Weil es voller Unit-Tests ist, um genau zu sein: Unit-Tests und automatisierte Integrationstests. (Schon mal was von Gurken gehört?) Und hier ist das Beste: Diese (noch) nicht verwendbare Software wurde von einem Unternehmen entwickelt, dessen Mitarbeiter Vorreiter in der testgetriebenen Entwicklungsszene sind. : D
Also mein Vorschlag ist:
Beginnen Sie mit dem Schreiben von Tests, nachdem Sie das Grundgerüst entwickelt haben. Andernfalls kann Refactoring schmerzhaft sein. Als Entwickler, der für andere entwickelt, bekommt man die Anforderungen nie gleich zu Beginn.
Stellen Sie sicher, dass Ihre Unit-Tests schnell durchgeführt werden können. Wenn Sie Integrationstests (wie Gurken) haben, ist es in Ordnung, wenn sie etwas länger dauern. Aber Langzeittests machen keinen Spaß, glauben Sie mir. (Die Leute vergessen alle Gründe, warum C ++ weniger populär geworden ist ...)
Überlassen Sie dieses TDD-Zeug den TDD-Experten.
Und ja, manchmal konzentrieren Sie sich auf Randfälle, manchmal auf die häufigsten Fälle, je nachdem, wo Sie das Unerwartete erwarten. Wenn Sie jedoch immer das Unerwartete erwarten, sollten Sie Ihren Workflow und Ihre Disziplin wirklich überdenken. ;-)
quelle
Leave this TDD stuff to the TDD-experts
.Wenn Sie zuerst mit Test Driven Development testen, wird Ihre Abdeckung im Bereich von 90% oder höher liegen, da Sie keine Funktionalität hinzufügen werden, ohne zuerst einen fehlgeschlagenen Komponententest dafür zu schreiben.
Wenn Sie später Tests hinzufügen, kann ich nicht genug empfehlen, dass Sie eine Kopie von Working Effectively With Legacy Code von Michael Feathers erhalten und sich einige der Techniken ansehen, mit denen Sie Ihrem Code Tests hinzufügen und Ihren Code umgestalten können um es testbarer zu machen.
quelle
The problem is, I don't know _what_ to test
Wenn Sie beginnen folgende Test Driven Development Praktiken, werden sie sortieren führen Sie durch den Prozess und zu wissen , was natürlich kommt zu testen. Einige Orte zum Starten:
Tests kommen zuerst
Schreiben Sie niemals Code, bevor Sie die Tests schreiben. Eine Erklärung finden Sie unter Rot-Grün-Refaktor-Wiederholung .
Schreiben Sie Regressionstests
Wenn Sie auf einen Fehler stoßen, schreiben Sie einen Testfall und vergewissern Sie sich, dass er fehlschlägt . Wenn Sie einen Fehler nicht durch einen fehlerhaften Testfall reproduzieren können, haben Sie ihn nicht wirklich gefunden.
Rot-Grün-Refaktor-Repeat
Rot : Schreiben Sie zunächst einen einfachen Test für das Verhalten, das Sie implementieren möchten. Stellen Sie sich diesen Schritt so vor, dass Sie einen Beispielcode schreiben, der die Klasse oder Funktion verwendet, an der Sie arbeiten. Stellen Sie sicher, dass es kompiliert / keine Syntaxfehler aufweist und dass es fehlschlägt . Dies sollte offensichtlich sein: Sie haben keinen Code geschrieben, also muss er fehlschlagen, oder? Das Wichtigste, was Sie hier lernen müssen, ist, dass Sie niemals sicher sein können, dass der Test, wenn er nicht bestanden wird, aufgrund einer falschen Begründung durchgeführt wird.
Grün : Schreiben Sie den einfachsten und dümmsten Code, der den Test tatsächlich besteht. Versuche nicht schlau zu sein. Selbst wenn Sie feststellen, dass es einen offensichtlichen Edge-Fall gibt, der Test dies jedoch berücksichtigt, schreiben Sie keinen Code, um damit umzugehen (aber vergessen Sie den Edge-Fall nicht: Sie werden ihn später benötigen). Die Idee ist, dass jeder Code, den Sie schreiben, jeder
if
, jedertry: ... except: ...
durch einen Testfall gerechtfertigt sein sollte. Der Code muss nicht elegant, schnell oder optimiert sein. Sie möchten nur, dass der Test bestanden wird.Refactor : Bereinigen Sie Ihren Code und geben Sie die richtigen Methodennamen ein. Überprüfen Sie, ob der Test noch besteht. Optimieren. Führen Sie den Test erneut aus.
Wiederholen : Sie erinnern sich an den Randfall, den der Test nicht behandelt hat, oder? Nun ist es also ein großer Moment. Schreiben Sie einen Testfall, der diese Situation abdeckt, beobachten Sie, wie er fehlschlägt, schreiben Sie Code, sehen Sie, wie er erfolgreich ist, und überarbeiten Sie ihn.
Testen Sie Ihren Code
Sie arbeiten an einem bestimmten Code, und genau das möchten Sie testen. Dies bedeutet, dass Sie keine Bibliotheksfunktionen, die Standardbibliothek oder Ihren Compiler testen sollten. Versuchen Sie auch zu vermeiden, die "Welt" zu testen. Dies beinhaltet: Aufrufen von externen Web-APIs, datenbankintensives Material usw. Wann immer Sie versuchen können, ein Modell zu erstellen (erstellen Sie ein Objekt, das der gleichen Schnittstelle folgt, jedoch statische, vordefinierte Daten zurückgibt).
quelle
Beginnen Sie bei Komponententests mit dem Testen, ob das Gerät das tut, wofür es entwickelt wurde. Das sollte der allererste Fall sein, den Sie schreiben. Wenn ein Teil des Entwurfs lautet "Es sollte eine Ausnahme auslösen, wenn Sie Junk übergeben", testen Sie dies ebenfalls, da dies Teil des Entwurfs ist.
Fang damit an. Wenn Sie mit den Grundlagen des Testens vertraut sind, lernen Sie, ob dies ausreicht, und lernen andere Aspekte Ihres Codes kennen, die getestet werden müssen.
quelle
Die Standardantwort lautet "alles testen, was brechen könnte" .
Was ist zu einfach zu brechen? Datenfelder, hirntote Zugriffsmethoden für Objekte und ähnliches. Alles andere implementiert wahrscheinlich einen identifizierbaren Teil einer Anforderung und kann vom Testen profitieren.
Natürlich können Ihre Laufleistung - und die Praktiken Ihres Arbeitsumfelds - variieren.
quelle