Wie wertvoll ein bestimmter Testansatz ist, hängt davon ab, wie geschäftskritisch das zu entwickelnde System ist und wie sehr ein anderes geschäftskritisches System davon abhängt. Ein einfaches Gästebuch-Skript für Ihre Website kann kaum als geschäftskritisch eingestuft werden. Wenn jedoch die Website, auf der es ausgeführt wird, durch einen Fehler, der eine ungefilterte Eingabe in die Datenbank ermöglichte und auf der diese Website einen wichtigen Service bietet, möglicherweise gefährdet wird, wird sie plötzlich viel umfangreicher wichtig, dass das Gästebuch-Skript gründlich getestet wird. Gleiches gilt auch für Framework / Bibliothekscode. Wenn Sie ein Framework mit einem Fehler entwickeln, weist jede Anwendung, die diese Framework-Funktion verwendet, denselben Fehler auf.
Testgetriebene Entwicklung gibt Ihnen zusätzliche Sicherheit, wenn es um Tests geht. Wenn Sie die Tests neben oder sogar nach dem Code schreiben, den Sie testen möchten, besteht ein echtes Risiko, dass Sie die Tests falsch verstehen. Wenn Sie zuerst alle Tests schreiben, kann die interne Funktionsweise des Codes keinen Einfluss darauf haben, wofür Sie Tests schreiben. Daher besteht weniger die Möglichkeit, dass Sie versehentlich Tests schreiben, die glauben, dass eine bestimmte fehlerhafte Ausgabe korrekt ist.
Testgetriebene Entwicklung ermutigt Ihre Entwickler auch, Code zu schreiben, der einfach zu testen ist, da sie sich nicht noch mehr Arbeit geben möchten! Code, der einfach zu testen ist, ist in der Regel einfach zu verstehen, wiederzuverwenden und zu warten.
Und die Wartung ist der Ort, an dem Sie die Vorteile von TDD wirklich nutzen können. Der überwiegende Teil des Programmieraufwands für Software ist wartungsbedingt. Dies bedeutet, Änderungen am Live-Code vorzunehmen, um ihm neue Funktionen zu verleihen, Fehler zu beheben oder ihn an neue Situationen anzupassen. Wenn Sie solche Änderungen vornehmen, möchten Sie sicherstellen, dass die von Ihnen vorgenommenen Änderungen den gewünschten Effekt haben, und, was noch wichtiger ist, dass sie keine unerwarteten Auswirkungen haben. Wenn Sie über eine vollständige Testsuite für Ihren Code verfügen, können Sie leicht überprüfen, ob alle vorgenommenen Änderungen nichts anderes beschädigen. Wenn die vorgenommenen Änderungen etwas anderes beschädigen, können Sie den Grund dafür schnell ermitteln. Die Vorteile sind langfristig.
Sie haben in Ihrer Frage Folgendes gesagt:
Ich sehe einen gewissen Vorteil darin, Tests für einige Dinge zu schreiben, aber nur für sehr wenige. Und obwohl mir die Idee gefällt, den Test zuerst zu schreiben, verbringe ich wesentlich mehr Zeit damit, meine Tests zu debuggen, damit sie sagen, was ich wirklich meine, als tatsächlichen Code zu debuggen. Dies liegt wahrscheinlich daran, dass der Testcode oft wesentlich komplizierter ist als der Code, den er testet. Ich hoffe, dies ist nur Unerfahrenheit mit den verfügbaren Tools (in diesem Fall rspec).
Dies scheint mir zu suggerieren, dass Sie nicht ganz auf die Probe gestellt werden. Ein Unit-Test soll extrem einfach sein, nur eine Folge von Methodenaufrufen, gefolgt von einer Aussage, um das erwartete Ergebnis mit dem tatsächlichen Ergebnis zu vergleichen. Sie sollten einfach sein, da Fehler in Ihren Tests katastrophal wären. Wenn Sie Schleifen, Verzweigungen oder andere Programmfunktionen in den Test einführen, ist es wahrscheinlicher, dass der Test einen Fehler enthält. Wenn Sie viel Zeit mit dem Debuggen von Tests verbringen, bedeutet dies, dass Ihre Tests zu kompliziert sind und Sie sie vereinfachen sollten.
Wenn die Tests nicht vereinfacht werden können, deutet allein diese Tatsache darauf hin, dass mit dem getesteten Code etwas nicht stimmt. Wenn Ihre Klasse beispielsweise über lange Methoden, Methoden mit vielen if / elseif / else- oder switch-Anweisungen oder eine große Anzahl von Methoden verfügt, deren komplexe Interaktionen vom aktuellen Status der Klasse bestimmt werden, müssen die Tests zwangsläufig äußerst komplex sein um vollständige Codeabdeckung bereitzustellen und alle Eventualitäten zu testen. Wenn Ihre Klasse fest codierte Abhängigkeiten von anderen Klassen aufweist, erhöht dies erneut die Anzahl der Rahmen, zu denen Sie springen müssen, um Ihren Code effektiv zu testen.
Wenn Sie Ihre Klassen klein und stark fokussiert halten, kurze Methoden mit wenigen Ausführungspfaden verwenden und versuchen, den internen Status zu beseitigen, können die Tests vereinfacht werden. Und das ist der springende Punkt. Guter Code ist von Natur aus leicht zu testen. Wenn der Code nicht einfach zu testen ist, stimmt wahrscheinlich etwas nicht.
Unit-Tests zu schreiben ist etwas, das Ihnen auf lange Sicht zugute kommt. Wenn Sie diese vermeiden, sparen Sie sich einfach Ärger für später. Sie kennen das Konzept der technischen Verschuldung vielleicht nicht, aber es funktioniert ähnlich wie die Finanzverschuldung. Keine Tests schreiben, keinen Code kommentieren, in fest codierte Abhängigkeiten schreiben und so weiter, um Schulden zu machen. Sie "leihen" sich die Zeit, indem Sie frühzeitig Abstriche machen, und dies kann Ihnen helfen, einen engen Termin einzuhalten, aber die Zeit, die Sie früher im Projekt sparen, ist ausgeliehen. Jeder Tag, der vergeht, ohne den Code zu bereinigen, richtig zu kommentieren oder eine Testsuite zu erstellen, kostet Sie Interesse. Je länger es dauert, desto mehr Zinsen fallen an. Schließlich werden Sie feststellen, dass Ihr Code zu einem Wirrwarr geworden ist, an dem Sie keine Änderungen vornehmen können, ohne unbeabsichtigte Konsequenzen auszulösen.
Sie könnten daran denken, Unit-Tests frühzeitig zu schreiben und sie als eine Form des "technischen Kredits" auf dem neuesten Stand zu halten. Sie investieren Zeit in die Bank, indem Sie sie frühzeitig in das Befolgen bewährter Praktiken investieren. Sie werden später Interesse an dieser Vorausschau haben, wenn Sie die Wartungsphase des Projekts erreichen. Wenn Sie eine Änderung vornehmen möchten, können Sie auf einfache Weise die Richtigkeit der Änderung überprüfen und feststellen, dass sie keine unerwünschten Nebenwirkungen hat. Außerdem können Sie Aktualisierungen schnell und unkompliziert herausbringen. Wenn Fehler auftauchen, können Sie einen neuen Komponententest hinzufügen, der den Fehler auslöst, und dann den Fehler im Code beheben. Wenn Sie den Unit-Test das nächste Mal ausführen, können Sie überprüfen, ob der Fehler behoben wurde und keine weiteren Probleme aufgetreten sind. Darüber hinaus werden Sie "Regressionen" vermeiden,
TL: DR - Ja, sie sind eine echte Hilfe, aber eine Investition. Die Vorteile werden erst später ersichtlich.