it-swarm.com.de

Müssen Tests für einfache (in sich geschlossene) Funktionen durchgeführt werden?

Bedenken Sie:

public function polynominal($a, $b, $c, $d)
{
    return  $a * pow($x, 3) + $b * pow($x, 2) + $c * $x + $d;
}

Angenommen, Sie schreiben verschiedene Tests für die oben genannte Funktion und beweisen sich und anderen, dass "es funktioniert".

Warum nicht diese Tests entfernen und glücklich leben? Mein Punkt ist, dass einige Funktionen nicht kontinuierlich getestet werden müssen, nachdem nachgewiesen wurde, dass sie funktionieren. Ich suche nach Kontrapunkten, die besagen, ja, diese Funktionen müssen noch getestet werden, weil: ... oder dass ja, diese müssen nicht getestet werden ...

36
Dennis

Regressionstests

Es geht um Regressionstests .

Stellen Sie sich vor, der nächste Entwickler betrachtet Ihre Methode und bemerkt, dass Sie magische Zahlen verwenden. Ihm wurde gesagt, dass magische Zahlen böse sind, also erstellt er zwei Konstanten, eine für die Nummer zwei, die andere für die Nummer drei - es ist nichts Falsches daran, diese Änderung vorzunehmen; Es ist nicht so, als hätte er Ihre bereits korrekte Implementierung geändert.

Abgelenkt kehrt er zwei Konstanten um.

Er schreibt den Code fest, und alles scheint gut zu funktionieren, da nach jedem Festschreiben keine Regressionstests ausgeführt werden.

Eines Tages (könnte Wochen später sein) bricht woanders etwas zusammen. Und mit anderswo meine ich an der völlig entgegengesetzten Stelle der Codebasis, was nichts mit der Funktion polynominal zu tun zu haben scheint. Stunden schmerzhaftes Debuggen führen zum Täter. Während dieser Zeit schlägt die Anwendung in der Produktion weiterhin fehl, was Ihren Kunden viele Probleme bereitet.

Wenn Sie die von Ihnen geschriebenen Originaltests beibehalten, können solche Schmerzen vermieden werden. Der abgelenkte Entwickler würde den Code festschreiben und fast sofort sehen, dass er etwas kaputt gemacht hat; Ein solcher Code erreicht nicht einmal die Produktion. Unit-Tests sind zusätzlich sehr genau über den Ort des Fehlers . Es wäre nicht schwierig, es zu lösen.

Ein Nebeneffekt...

Tatsächlich basiert das meiste Refactoring stark auf Regressionstests. Nehmen Sie eine kleine Änderung vor. Prüfung. Wenn es vorbei ist, ist alles in Ordnung.

Der Nebeneffekt ist, dass praktisch jedes Refactoring ein großes Risiko darstellt, den Code zu beschädigen, wenn Sie keine Tests haben. In vielen Fällen ist es bereits schwierig, dem Management zu erklären, dass Refactoring sollte durchgeführt werden soll. Dies ist jedoch noch schwieriger, nachdem Ihre vorherigen Refactoring-Versuche mehrere Fehler verursacht haben.

Durch eine vollständige Testsuite fördern Sie das Refactoring und damit den saubereren Code. Ohne Risiko wird es sehr verlockend, regelmäßig mehr umzugestalten.

Änderungen der Anforderungen

Ein weiterer wesentlicher Aspekt ist, dass sich die Anforderungen ändern. Möglicherweise werden Sie aufgefordert, m komplexe Zahlen zu verarbeiten , und plötzlich müssen Sie Ihr Versionskontrollprotokoll durchsuchen, um die vorherigen Tests zu finden, sie wiederherzustellen und neue Tests hinzuzufügen.

Warum all dieser Ärger? Warum Tests entfernen, um sie später hinzuzufügen? Du hättest sie an erster Stelle behalten können.

78

Weil nichts so einfach ist, dass es keine Fehler geben kann.

Ihr Code scheint auf den ersten Blick fehlerfrei zu sein. Es ist in der Tat eine einfache programmatische Darstellung einer Polynomfunktion.

Außer es hat einen Fehler ...

public function polynominal($a, $b, $c, $d)
{
    return  $a * pow($x, 3) + $b * pow($x, 2) + $c * $x + $d;
}

$x ist nicht als Eingabe für Ihren Code definiert. Abhängig von der Sprache, der Laufzeit oder dem Umfang funktioniert Ihre Funktion möglicherweise nicht, führt zu ungültigen Ergebnissen oder kann ein Raumschiff zum Absturz bringen .


Nachtrag:

Während Sie Ihren Code vorerst als fehlerfrei betrachten, ist es schwer zu sagen, wie lange dies der Fall bleibt. Es könnte zwar argumentiert werden, dass sich das Schreiben eines Tests für solch einen trivialen Code nicht lohnt, aber nachdem der Test bereits geschrieben wurde, ist die Arbeit erledigt und das Löschen eines Tests ist ein greifbarer Schutz.

Besonders hervorzuheben sind Codeabdeckungsdienste (wie coveralls.io), die einen guten Hinweis auf die Abdeckung geben, die eine Testsuite bietet. Indem Sie jede Codezeile abdecken, geben Sie eine anständige Metrik für die Menge (wenn nicht die Qualität) der von Ihnen durchgeführten Tests an. In Kombination mit vielen kleinen Tests sagen Ihnen diese Dienste zumindest, wo nicht nach einem Fehler suchen muss, wenn er auftritt.

Wenn Sie bereits einen Test geschrieben haben, behalten Sie ihn . Da die Platz- oder Zeitersparnis beim Löschen wahrscheinlich viel geringer ist als die technische Verschuldung später, wenn ein Fehler auftritt.

44
user69037

Ja. Wenn wir mit 100% iger Sicherheit mit Sicherheit sagen könnten: Diese Funktion wird niemals bearbeitet und niemals in einem Kontext ausgeführt, der zum Fehlschlagen führen könnte. Wenn wir das sagen könnten, könnten wir die Tests löschen und jeweils ein paar Millisekunden sparen CI Build.

Aber wir können nicht. Oder wir können nicht mit vielen Funktionen. Und es ist einfacher, die Regel zu haben, alle Tests ständig auszuführen, als sich die Mühe zu machen, genau zu bestimmen, mit welcher Vertrauensschwelle wir zufrieden sind und wie viel Vertrauen wir in die Unveränderlichkeit und Unfehlbarkeit einer bestimmten Funktion haben.

Und die Bearbeitungszeit ist günstig. Diese Millisekunden, die gespeichert oder sogar um ein Vielfaches vervielfacht wurden, reichen nicht aus, um zu rechtfertigen, dass wir uns bei jeder Funktion die Zeit nehmen, um zu fragen: Haben wir genügend Vertrauen, dass wir sie nie wieder testen müssen?

21
Carl Manaster

Alles, was in den anderen Antworten gesagt wurde, ist korrekt, aber ich werde noch eine hinzufügen.

Dokumentation

Wenn Unit-Tests gut geschrieben sind, können sie einem Entwickler genau erklären, was eine Funktion tut, welche Eingabe-/Ausgabeerwartungen sie hat und was noch wichtiger ist, welches Verhalten von ihr erwartet werden kann.

Dies kann das Erkennen eines Fehlers erleichtern und die Verwirrung verringern.

Nicht jeder erinnert sich an Polynome, Geometrie oder sogar Algebra :) Aber ein guter Komponententest, der in die Versionskontrolle eingecheckt wurde, wird mir in Erinnerung bleiben.

Ein Beispiel dafür, wie nützlich es als Dokumentation sein kann, finden Sie in der Jasmine-Einführung: http://jasmine.github.io/Edge/introduction.html Geben Sie ihm einige Sekunden zum Laden und scrollen Sie dann zum Boden. Sie sehen die gesamte Jasmine-API als Unit-Test-Ausgabe dokumentiert.

[Aktualisierung basierend auf dem Feedback von @Warbo] Tests sind garantiert ebenfalls aktuell, da sie andernfalls fehlschlagen, was im Allgemeinen zu einem Build-Fehler führt, wenn CI verwendet wird. Die externe Dokumentation ändert sich unabhängig vom Code und ist daher nicht unbedingt aktuell.

12
Brandon

Reality-Check

Ich war in herausfordernden Umgebungen, in denen das Testen während der Budgetierung und des Zeitplans "Zeitverschwendung" und dann "ein grundlegender Teil der Qualitätssicherung" ist, sobald der Kunde mit Fehlern zu tun hat. Daher ist meine Meinung flüssiger als andere.

Sie haben ein Budget. Ihre Aufgabe ist es, das bestmögliche Produkt für dieses Budget zu erhalten, unabhängig von der Definition von "best", die Sie zusammenkratzen können (es ist kein leicht zu definierendes Wort). Ende der Geschichte.

Testen ist a Werkzeug in Ihrem Inventar. Sie sollten es verwenden , weil es ein gutes Werkzeug ist, mit einer langen Geschichte des Sparens von Millionen oder vielleicht sogar Milliarden von Dollar. Wenn Sie eine Chance haben, sollten Sie diesen einfachen Funktionen Tests hinzufügen. Es kann Ihre Haut eines Tages retten.

In der realen Welt kann dies jedoch mit Budget- und Zeitplanbeschränkungen nicht passieren. Mach dich nicht zum Sklaven der Prozedur. Testfunktionen sind nett, aber irgendwann können Sie Ihre Arbeitsstunden besser damit verbringen, Entwicklerdokumentation in Worten anstatt in Code zu schreiben, sodass der nächste Entwickler weniger Tests benötigt. Oder es ist besser, die Codebasis zu überarbeiten, damit Sie sich nicht so schwer wie ein Biest halten müssen. Oder vielleicht ist es besser, diese Zeit damit zu verbringen, mit Ihrem Chef über das Budget und den Zeitplan zu sprechen, damit er oder sie besser versteht, wofür sie bieten, wenn die nächste Finanzierungsrunde ansteht.

Softwareentwicklung ist ein Gleichgewicht. Zählen Sie immer die Opportunitätskosten für alles, was Sie tun, um sicherzustellen, dass es keinen besseren Weg gibt, Ihre Zeit zu verbringen.

2
Cort Ammon

Ja, halten Sie die Tests aufrecht, lassen Sie sie laufen und bestehen Sie sie weiter.

Unit-Tests dienen dazu, Sie (und andere) vor sich selbst (und sich selbst) zu schützen.

Warum ist es eine gute Idee, die Tests beizubehalten?

  • Überprüfen Sie die Funktionalität der vorherigen Anforderungen angesichts neuer Anforderungen und zusätzlicher Funktionen
  • Stellen Sie sicher, dass die Refactoring-Übungen korrekt sind
  • Interne Dokumentation - So soll der Code verwendet werden
  • Regressionstests, Dinge ändern sich
    • Brechen die Änderungen den alten Code?
    • Erfordern die Änderungen weitere Änderungsanforderungen oder Aktualisierungen der aktuellen Funktionen oder des Codes?
  • Da die Tests bereits geschrieben sind, bewahren Sie sie auf. Es ist Zeit und Geld, die bereits ausgegeben werden, um die Wartungskosten später zu senken
0
Niall