Ich arbeite in einer kleinen Firma als Solo-Entwickler. Ich bin der einzige Entwickler im Unternehmen. Ich habe mehrere (relativ) große Projekte, die ich regelmäßig geschrieben und gepflegt habe, und keines hat Tests, um sie zu unterstützen. Wenn ich neue Projekte beginne, frage ich mich oft, ob ich einen TDD-Ansatz ausprobieren soll. Es klingt nach einer guten Idee, aber ich kann die zusätzliche Arbeit ehrlich gesagt nie rechtfertigen.
Ich arbeite hart, um in meinem Design zukunftsorientiert zu sein. Mir ist klar, dass sicherlich eines Tages ein anderer Entwickler meinen Code warten oder zumindest Fehler beheben muss. Ich halte die Dinge so einfach wie möglich und kommentiere und dokumentiere Dinge, die schwer zu begreifen sind. Und die Tatsache ist, dass diese Projekte nicht so groß oder kompliziert sind, dass ein anständiger Entwickler Schwierigkeiten haben würde, sie zu verstehen.
Viele der Beispiele, die ich bei Tests gesehen habe, betreffen alle Aspekte des Codes. Da ich der einzige Entwickler bin und dem Code im gesamten Projekt sehr nahe bin, ist es viel effizienter, ein Schreib- als auch ein manuelles Testmuster zu befolgen. Ich stelle auch fest, dass sich Anforderungen und Funktionen häufig genug ändern, um bei der Beibehaltung von Tests einen erheblichen Aufwand für ein Projekt zu verursachen. Zeit, die sonst für die Lösung der geschäftlichen Anforderungen aufgewendet werden könnte.
So komme ich jedes Mal zu dem gleichen Schluss. Die Kapitalrendite ist zu niedrig.
Ich habe gelegentlich ein paar Tests eingerichtet, um sicherzustellen, dass ich einen Algorithmus richtig geschrieben habe, wie zum Beispiel die Anzahl der Jahre, die jemand im Unternehmen war, basierend auf dem Einstellungsdatum. Aber vom Standpunkt der Codeabdeckung aus habe ich ungefähr 1% meines Codes abgedeckt.
Würden Sie in meiner Situation immer noch einen Weg finden, Unit-Tests zu einer regelmäßigen Praxis zu machen, oder bin ich berechtigt, diesen Aufwand zu vermeiden?
UPDATE: Einige Dinge über meine Situation, die ich ausgelassen habe: Meine Projekte sind alle Webanwendungen. Um meinen gesamten Code abzudecken, müsste ich automatisierte UI-Tests verwenden, und in diesem Bereich sehe ich immer noch keinen großen Vorteil gegenüber manuellen Tests.
quelle
Antworten:
Damit? Sie müssen nicht alles testen . Nur die relevanten Dinge.
Das ist eigentlich falsch. Effizienter geht es nicht. Es ist wirklich nur eine Gewohnheit.
Was andere Solo-Entwickler tun, ist eine Skizze oder einen Umriss zu schreiben, die Testfälle zu schreiben und dann den Umriss mit dem endgültigen Code auszufüllen.
Das ist sehr, sehr effizient.
Das ist auch falsch. Die Tests sind nicht der Widerstand. Die Änderungen der Anforderungen sind der Widerstand.
Sie müssen die Tests korrigieren, um die Anforderungen widerzuspiegeln. Ob ihre minutiae oder High-Level; zuerst geschrieben oder zuletzt geschrieben.
Der Code wird erst nach Bestehen der Tests ausgeführt. Das ist die universelle Wahrheit von Software.
Sie können einen begrenzten "Here it is" -Abnahmetest durchführen.
Oder Sie können einige Unit-Tests haben.
Oder Sie können beides haben.
Aber egal was Sie tun, es gibt immer einen Test, um zu demonstrieren, dass die Software funktioniert.
Ich würde vorschlagen, dass ein bisschen Formalität und eine nette Unit-Test-Tool-Suite diesen Test viel nützlicher machen.
quelle
sqrt(-1)
sich um eine Ganzzahl handeln soll, erhalten Sie überwältigende Rückmeldungen. Das Gleichgewicht liegt bei "wie" und "welcher Reihenfolge". Die bloße Tatsache ist, dass Sie testen müssen . Schreiben Sie also zuerst die Tests und stellen Sie sicher, dass sie funktionieren.Stellen Sie sich vor, Sie hätten eine Reihe von Tests, die in einem Eyeblink ausgeführt werden könnten und ein grünes oder rotes Licht aufleuchten lassen. Stellen Sie sich vor, diese Testsuite hat alles getestet ! Stellen Sie sich vor, Sie müssten nur ^ T eingeben, um die Testsuite auszuführen. Welche Macht würde dir das geben?
Könnten Sie den Code ändern, ohne Angst zu haben, etwas zu beschädigen? Können Sie ein neues Feature hinzufügen, ohne befürchten zu müssen, ein altes Feature zu beschädigen? Können Sie unordentlichen Code schnell bereinigen, ohne befürchten zu müssen, Schaden anzurichten?
Ja, du könntest all diese Dinge tun! Und was würde mit Ihrem Code im Laufe der Zeit passieren? Es würde sauberer und sauberer werden, da es kein Risiko geben würde, es zu reinigen.
Stellen wir uns vor, Sie hätten eine kleine Fee auf der Schulter. Jedes Mal, wenn Sie eine Codezeile geschrieben haben, fügte die Fee der Testsuite etwas hinzu, das prüfte, ob diese Codezeile das tat, was sie tun sollte. So konnten Sie alle paar Sekunden ^ T drücken und sehen, dass die letzte Codezeile, die Sie geschrieben haben, funktioniert hat.
Wie viel Debugging würdest du tun?
Wenn das nach Fantasie klingt, haben Sie recht. Aber die Realität sieht nicht viel anders aus. Ersetzen Sie den Eyeblink durch ein paar Sekunden und die Fee durch die TDD-Disziplin, und Sie haben es so ziemlich geschafft.
Angenommen, Sie kehren zu einem System zurück, das Sie vor einem Jahr erstellt haben, und Sie haben vergessen, eines der zentralen Objekte zu erstellen. Es gibt Tests, die das Objekt so erstellen, wie es erstellt werden kann. Sie können diese Tests lesen und Ihr Gedächtnis auf Trab halten. Müssen Sie eine API aufrufen? Es gibt Tests, die diese API so aufrufen, wie sie aufgerufen werden kann. Diese Tests sind kleine Dokumente , die in einer Sprache verfasst sind , die Sie verstehen. Sie sind völlig eindeutig. Sie sind so förmlich, dass sie ausgeführt werden. Und sie können nicht mit der Anwendung synchronisiert werden!
Lohnt sich die Investition nicht? Du willst mich wohl veralbern! Wie konnte jemand diese Testreihe NICHT wollen? Tu dir selbst einen Gefallen und hör auf, über Albernheit zu streiten. Erfahren Sie, wie Sie TDD gut beherrschen und wie viel schneller Sie arbeiten und wie viel sauberer Ihr Code ist.
quelle
Der Fehler, den Sie machen, besteht darin, dass Sie das Testen als Zeitinvestition ohne unmittelbare Rendite ansehen. Das muss nicht so funktionieren.
Das Schreiben von Tests konzentriert Sie zunächst wirklich darauf, was dieser Teil Ihres Codes zu tun hat.
Wenn Sie sie zweitens ausführen, werden Fehler aufgedeckt, die andernfalls beim Testen auftreten würden.
Drittens zeigt das Ausführen manchmal Fehler, die sonst beim Testen nicht aufgetaucht wären, und beißen Sie dann in der Produktion wirklich in den Arsch.
Viertens: Wenn Sie einen Fehler mit einem laufenden System feststellen und einen Komponententest für diesen Fehler erstellen, können Sie diesen Fehler später nicht erneut einführen. Das kann eine große Hilfe sein. Wiedereintretende Fehler sind häufig und sehr ärgerlich.
Fünftens: Wenn Sie jemals Code an eine andere Person übergeben müssen, erleichtert eine Testsuite deren Leben erheblich. Auch wenn Sie ein Projekt ignoriert haben und nach ein paar Jahren wieder darauf zurückkommen, werden Sie nicht mehr so nah dran sein und es wird auch für Sie hilfreich sein.
Ich habe durchweg die Erfahrung gemacht, dass bei der Entwicklung eines Projekts durch ordnungsgemäße Komponententests der Prozess immer schneller und zuverlässiger wurde.
quelle
Die Jungs von JUnit (Java Unit Test Framework) haben die Philosophie, dass wenn es zu einfach ist zu testen, testen Sie es nicht . Ich empfehle dringend, die häufig gestellten Fragen zu Best Practices zu lesen , da sie ziemlich pragmatisch sind.
TDD ist ein anderer Prozess zum Schreiben Ihrer Software. Die Grundvoraussetzung für Unit-Tests ist, dass Sie weniger Zeit für den Debugger aufwenden müssen, um den Code durchzuarbeiten, und schneller herausfinden, ob Ihre Codeänderung versehentlich etwas anderes im System zerstört. Das passt zu TDD. Der TDD-Zyklus sieht folgendermaßen aus:
Was bei der Anwendung von TDD weniger offensichtlich ist, ist, dass es die Art und Weise ändert, in der Sie Code schreiben . Indem Sie sich zwingen, darüber nachzudenken, wie Sie die Funktionsfähigkeit des Codes testen / validieren, schreiben Sie testbaren Code. Und da es sich um Unit-Tests handelt, bedeutet dies normalerweise, dass Ihr Code modularer wird. Modularer und testbarer Code ist für mich von vornherein ein großer Gewinn.
Müssen Sie jetzt Dinge wie C # -Eigenschaften testen? Stellen Sie sich eine Eigenschaft vor, die wie folgt definiert ist:
Die Antwort wäre "nein", es lohnt sich nicht zu testen, da Sie zu diesem Zeitpunkt die Sprachfunktion testen. Vertrauen Sie einfach darauf, dass die C # -Plattform-Leute es richtig verstanden haben. Außerdem, wenn es fehlschlug, was könnten Sie tun, um es zu beheben?
Außerdem werden Sie feststellen, dass bestimmte Teile Ihres Codes zu aufwendig sind, um sie ordnungsgemäß zu testen. Das heißt, tun Sie es nicht, sondern stellen Sie sicher, dass Sie den Code testen, der für das heikle Problem verwendet wird:
Ob Sie es glauben oder nicht, TDD wird Ihnen helfen, in ein nachhaltiges Entwicklungstempo zu geraten. Das liegt nicht an der Magie, sondern daran, dass Sie eine enge Rückkopplungsschleife haben und wirklich dumme Fehler schnell erkennen können. Die Kosten für die Behebung dieser Fehler sind im Wesentlichen konstant (zumindest für Planungszwecke ausreichend), da die kleinen Fehler niemals zu großen Fehlern werden. Vergleichen Sie das mit der Burstigkeit von Code-Binge- / Debug-Purge-Sprints.
quelle
Sie müssen die Kosten für das Testen mit den Kosten für Fehler in Einklang bringen.
Das Schreiben eines 10-Zeilen-Unit-Tests für eine Funktion, die eine Datei öffnet, bei der der Fehler "Datei nicht gefunden" lautet, ist sinnlos.
Eine Funktion, die etwas Komplexes mit einer komplexen Datenstruktur macht - dann natürlich ja.
Das Knifflige liegt dazwischen. Denken Sie jedoch daran, dass der wahre Wert von Komponententests nicht die jeweilige Funktion testet, sondern die kniffligen Wechselwirkungen zwischen ihnen. Ein Komponententest, der feststellt, dass eine Änderung an einem Codebit eine Funktion in einem anderen Modul in 1000 Zeilen Entfernung unterbricht, ist das Gewicht des Kaffees wert.
quelle
Testen ist Glücksspiel.
Das Erstellen eines Tests ist eine Wette, dass die Kosten für Fehler in einer Einheit, die bei diesem Test (jetzt und bei allen zukünftigen Code-Revisionen) auftreten und nicht abgefangen werden, höher sind als die Kosten für die Entwicklung des Tests. Zu diesen Kosten für die Testentwicklung zählen Dinge wie Gehaltsabrechnung für zusätzliche Testentwicklung, zusätzliche Markteinführungszeit, entgangene Opportunitätskosten durch das Nichtcodieren anderer Dinge usw.
Wie bei jeder Wette gewinnt man manchmal, manchmal verliert man.
Manchmal setzt sich späte Software mit weitaus weniger Fehlern gegen schnelles, aber fehlerhaftes Material durch, das zuerst auf den Markt kommt. Manchmal das Gegenteil. Sie müssen sich die Statistiken in Ihrem speziellen Bereich ansehen und wie viel Management spielen möchte.
Bei einigen Arten von Fehlern ist es möglicherweise so unwahrscheinlich, dass sie gemacht werden oder dass sie sich aus frühen Hygienetests ergeben, dass sich statistisch gesehen die Zeit nicht lohnt, zusätzliche spezifische Tests zu erstellen. Aber manchmal sind die Kosten eines Fehlers so hoch (medizinisch, nuklear usw.), dass ein Unternehmen eine Verlustwette abschließen muss (ähnlich wie beim Abschluss einer Versicherung). Viele Apps haben nicht so hohe Ausfallkosten und benötigen daher keinen höheren unwirtschaftlichen Versicherungsschutz. Andere tun es.
quelle
Mein Rat ist, nur den Code zu testen, den Sie richtig arbeiten möchten.
Testen Sie nicht den Code, der fehlerhaft sein soll, und verursachen Sie später Probleme.
quelle
TDD und Unit Testing sind nicht dasselbe.
Sie können Code schreiben und später Unit-Tests hinzufügen. Das ist kein TDD und eine Menge zusätzlicher Arbeit.
TDD ist die Praxis des Codierens in einer Rotlichtschleife. Grünes Licht. Refactor-Iterationen.
Dies bedeutet, dass Sie Tests für Code schreiben, der noch nicht vorhanden ist, die fehlgeschlagenen Tests beobachten, den Code korrigieren, damit die Tests funktionieren, und dann den Code "richtig" machen. Das erspart Ihnen oft Arbeit
Einer der Vorteile von TDD besteht darin, dass weniger über Wissenswertes nachgedacht werden muss. Dinge wie Off-by-One-Fehler verschwinden. Sie müssen die API-Dokumentation nicht durchsuchen, um herauszufinden, ob die zurückgegebene Liste bei 0 oder 1 beginnt.
quelle
Ich habe an einem System gearbeitet, in dem wir fast alles getestet haben. Die bemerkenswerten Ausführungen zum Testen waren der PDF- und XLS-Ausgabecode.
Warum? Wir konnten die Teile testen, die die Daten gesammelt und das Modell erstellt haben, mit dem die Ausgabe erstellt wurde. Wir konnten auch die Teile testen, die herausfanden, welche Teile des Modells in die PDF-Dateien passen würden. Wir konnten nicht testen, ob die PDF-Datei in Ordnung war, da dies völlig subjektiv war. Wir konnten nicht testen, ob alle Teile eines PDF-Dokuments für einen typischen Benutzer lesbar sind, da dies auch subjektiv war. Oder ob die Wahl zwischen Balken- und Kreisdiagrammen für den Datensatz richtig war.
Wenn die Ausgabe subjektiv sein soll, gibt es nur wenige Unit-Tests, die Sie durchführen können, was die Mühe wert ist.
quelle
In vielen Fällen dauert ein "Schreiben-Dann-Manuell-Test" nicht länger als ein paar Tests zu schreiben. Die Zeitersparnis ergibt sich aus der Möglichkeit, diese Tests jederzeit erneut durchzuführen.
Denken Sie daran: Wenn Sie bei Ihren Tests eine angemessene Funktionsabdeckung haben (nicht zu verwechseln mit der Codeabdeckung) und Sie beispielsweise 10 Funktionen haben - wenn Sie auf eine Schaltfläche klicken, haben Sie ungefähr 10 Jahre Zeit , Ihre Tests erneut durchzuführen ... während Sie sich zurücklehnen und Ihren Kaffee trinken.
Sie auch nicht haben , um die minutae zu testen. Sie können Integrationstests schreiben, die Ihre Funktionen abdecken, wenn Sie nicht auf die kleinsten Details eingehen möchten ... IMO, einige Komponententests sind zu detailliert, um Sprache und Plattform und nicht den Code zu testen.
TL; DR Es ist wirklich nie angebracht, weil die Vorteile einfach zu gut sind.
quelle
Zwei sehr gute Antworten, auf die ich gestoßen bin, sind hier:
Die Gründe für die Vermeidung von wahrgenommenem Overhead:
Möchten Sie nicht ein großartiges Produkt als Beweis für die Qualität Ihrer Arbeit hinterlassen? Sprichst du egoistisch, ist es nicht besser für dich, dass du es tust?
quelle
Professionelle Entwickler schreiben Komponententests, weil sie längerfristig Zeit sparen. Sie werden Ihren Code früher oder später testen, und wenn Sie dies nicht tun, und wenn Sie später Fehler beheben müssen, werden sie schwerer zu beheben sein und mehr Auswirkungen haben.
Wenn Sie Code ohne Tests schreiben und keine Bugs haben, ist das in Ordnung. Ich glaube nicht, dass Sie ein nicht-triviales System mit null Fehlern schreiben können, also gehe ich davon aus, dass Sie es auf die eine oder andere Weise testen.
Unit-Tests sind auch wichtig, um Regressionen beim Ändern oder Umgestalten von älterem Code zu vermeiden. Sie beweisen nicht, dass Ihre Änderung nicht den alten Code gebrochen hat, aber sie geben Ihnen viel Selbstvertrauen (solange sie natürlich bestehen :))
Ich würde nicht zurückgehen und eine ganze Reihe von Tests für Code schreiben, den Sie bereits ausgeliefert haben, aber wenn Sie das nächste Mal eine Funktion ändern müssen, würde ich vorschlagen, dass Sie versuchen, Tests für dieses Modul oder diese Klasse zu schreiben, erreichen Sie eine Abdeckung von bis zu 70%. +, bevor Sie Änderungen vornehmen. Sehen Sie, ob es Ihnen hilft.
Wenn Sie es versuchen und ehrlich sagen können, dass es keine Hilfe war, dann ist es fair genug, aber ich denke, es gibt genügend Indus- triebeweise, die dazu beitragen, dass es sich zumindest lohnt, den Ansatz zu testen.
quelle
Die meisten Antworten scheinen pro-TDD zu sein, obwohl die Frage nicht nach TDD, sondern nach Unit-Tests im Allgemeinen gestellt wurde.
Es gibt keine völlig objektive Regel dahinter, was der Komponententest oder nicht der Komponententest sein soll. Aber es gibt ein paar Male, bei denen es so aussieht, als würden viele Programmierer keinen Komponententest durchführen:
Abhängig von Ihrer OOP-Philosophie können Sie private Methoden erstellen, um komplexe Routinen von Ihren öffentlichen Methoden zu entkoppeln. Öffentliche Methoden sollen normalerweise an vielen verschiedenen Stellen aufgerufen und häufig verwendet werden, und die privaten Methoden werden nur von einer oder zwei öffentlichen Methoden in einer Klasse oder einem Modul wirklich aufgerufen, um etwas sehr Bestimmtes zu erreichen. In der Regel ist es ausreichend, Komponententests für öffentliche Methoden zu schreiben, nicht jedoch für die zugrunde liegenden privaten Methoden, die einen Teil der Magie auslösen. Wenn bei einer privaten Methode etwas schief geht, sollten Ihre Unit-Tests für öffentliche Methoden gut genug sein, um diese Probleme zu erkennen.
Viele neue Programmierer wenden sich dagegen, wenn sie das Testen zum ersten Mal lernen, und denken, dass sie jede einzelne ausgeführte Zeile testen müssen. Wenn Sie eine externe Bibliothek verwenden und deren Funktionalität von den Autoren gut getestet und dokumentiert wurde, ist es normalerweise sinnlos, die spezifische Funktionalität in Komponententests zu testen. Beispielsweise könnte jemand einen Test schreiben, um sicherzustellen, dass sein ActiveRecord-Modell den korrekten Wert für ein Attribut mit einem "before_save" -Rückruf für die Datenbank beibehält, obwohl dieses Verhalten in Rails bereits gründlich getestet wurde. Die Methode (n), die der Rückruf aufruft (aber nicht das Rückrufverhalten selbst). Grundlegende Probleme mit importierten Bibliotheken sollten eher durch Akzeptanztests als durch Komponententests aufgedeckt werden.
Beides könnte zutreffen, egal ob Sie TDD machen oder nicht.
quelle
Ken, ich und viele andere Entwickler sind im Laufe unserer Karriere mehrmals zu demselben Schluss gekommen wie Sie.
Die Wahrheit, von der ich glaube, dass Sie sie finden werden (wie viele andere auch), ist, dass die anfängliche Investition in das Schreiben von Tests für Ihre Anwendung entmutigend erscheint, aber wenn sie gut geschrieben und auf die richtigen Teile Ihres Codes ausgerichtet sind, können sie wirklich eine Menge sparen von Zeit.
Mein großes Problem waren die verfügbaren Test-Frameworks. Ich hatte nie das Gefühl, dass sie genau das sind, wonach ich gesucht habe, also habe ich einfach meine eigene, sehr einfache Lösung entwickelt. Es hat wirklich geholfen, mich auf die "dunkle Seite" der Regressionstests zu bringen. Ich werde ein grundlegendes Pseudo-Snippet von dem, was ich hier gemacht habe, teilen, und hoffentlich können Sie eine Lösung finden, die für Sie funktioniert.
Der einzige schwierige Teil danach ist, herauszufinden, welche Granularitätsstufe Ihrer Meinung nach für jedes Projekt die beste ist.
Das Erstellen eines Adressbuchs erfordert natürlich weniger Tests als eine Unternehmenssuchmaschine, aber die Grundlagen ändern sich nicht wirklich.
Viel Glück!
quelle