Ich finde Tests viel kniffliger und schwerer zu schreiben als den eigentlichen Code, den sie testen. Es ist nicht ungewöhnlich, dass ich mehr Zeit mit dem Schreiben des Tests verbringe als mit dem Code, den er testet.
Ist das normal oder mache ich etwas falsch?
Die Fragen „ Lohnt sich ein Unit-Test oder eine testgetriebene Entwicklung? „ Wir verbringen mehr Zeit mit der Implementierung von Funktionstests als mit der Implementierung des Systems selbst. Ist das normal? "Und ihre Antworten sind mehr darüber, ob sich das Testen lohnt (wie in" Sollen wir das Schreiben von Tests insgesamt auslassen? "). Obwohl ich davon überzeugt bin, dass Tests wichtig sind, frage ich mich, ob ich mehr Zeit für Tests aufgewendet habe als für den eigentlichen Code, oder ob es nur ich bin.
Gemessen an der Anzahl der Aufrufe, Antworten und positiven Bewertungen meiner Frage kann ich nur davon ausgehen, dass dies ein berechtigtes Anliegen ist, das in keiner anderen Frage auf der Website angesprochen wird.
quelle
Antworten:
Ich erinnere mich an einen Software-Engineering-Kurs, in dem einer ca. 10% der Entwicklungszeit für das Schreiben von neuem Code verwendet und die anderen 90% für das Debuggen, Testen und Dokumentieren.
Da Unit-Tests das Debugging und den Testaufwand in (möglicherweise automatisierbaren) Code erfassen, ist es sinnvoll, dass mehr Aufwand in sie fließt. Die tatsächliche Zeit sollte nicht viel länger sein als das Debuggen und Testen ohne das Schreiben der Tests.
Schließlich sollten Tests auch als Dokumentation dienen! Man sollte Unit-Tests so schreiben, wie der Code verwendet werden soll. dh die Tests (und die Benutzung) sollten einfach sein, das komplizierte Zeug in die Implementierung einfließen lassen.
Wenn Ihre Tests schwer zu schreiben sind, ist der Code, den sie testen, wahrscheinlich schwer zu verwenden!
quelle
Es ist.
Selbst wenn Sie nur Unit-Tests durchführen, ist es nicht ungewöhnlich, dass mehr Code in den Tests enthalten ist als der tatsächlich getestete Code. Daran ist nichts auszusetzen.
Betrachten Sie einen einfachen Code:
Was wären die Tests? Es gibt mindestens vier einfache Fälle, die hier getestet werden müssen:
Der Name der Person lautet
null
. Wird die Ausnahme tatsächlich geworfen? Das sind mindestens drei Zeilen Testcode, die geschrieben werden müssen.Der Name der Person lautet
"Jeff"
. Bekommen wir eine"Hello, Jeff!"
Antwort? Das sind vier Zeilen Testcode.Der Name der Person ist eine leere Zeichenfolge. Welche Leistung erwarten wir? Was ist die tatsächliche Ausgabe? Nebenfrage: Entspricht es den funktionalen Anforderungen? Das bedeutet weitere vier Codezeilen für den Unit-Test.
Der Name der Person ist kurz genug für eine Zeichenfolge, aber zu lang, um mit
"Hello, "
dem Ausrufezeichen kombiniert zu werden . Was passiert? ¹Dies erfordert viel Testcode. Darüber hinaus erfordern die elementarsten Codeteile häufig Setup-Code, der die für den zu testenden Code erforderlichen Objekte initialisiert, was auch häufig zum Schreiben von Stubs und Mocks usw. führt.
Wenn das Verhältnis sehr groß ist, können Sie in diesem Fall einige Dinge überprüfen:
Gibt es Code-Duplikationen zwischen den Tests? Die Tatsache, dass es sich um Testcode handelt, bedeutet nicht, dass der Code zwischen ähnlichen Tests dupliziert (kopiert und eingefügt) werden sollte. Eine solche Duplizierung erschwert die Wartung dieser Tests.
Gibt es redundante Tests? Als Faustregel gilt: Wenn Sie einen Komponententest entfernen, sollte sich die Zweigabdeckung verringern. Wenn dies nicht der Fall ist, wird möglicherweise angezeigt, dass der Test nicht benötigt wird, da die Pfade bereits von anderen Tests abgedeckt werden.
Testen Sie nur den Code, den Sie testen sollten? Es wird nicht erwartet, dass Sie das zugrunde liegende Framework der Bibliotheken von Drittanbietern testen , sondern ausschließlich den Code des Projekts selbst.
Mit Rauch-, System- und Integrationstests, Funktions- und Abnahmetests sowie Belastungs- und Belastungstests fügen Sie noch mehr Testcode hinzu, sodass Sie sich keine Sorgen machen sollten, vier oder fünf LOC-Tests für jeden LOC-Code zu haben.
Ein Hinweis zu TDD
Wenn Sie sich Sorgen über die Zeit machen, die zum Testen Ihres Codes erforderlich ist, liegt es möglicherweise an Ihnen, dass Sie etwas falsch machen. Das heißt, dass der Code zuerst und später getestet wird. In diesem Fall kann TDD helfen, indem es Sie ermutigt, in Iterationen von 15 bis 45 Sekunden zwischen Code und Tests zu wechseln. Laut den Befürwortern von TDD wird der Entwicklungsprozess beschleunigt, indem sowohl die Anzahl der erforderlichen Tests als auch, was noch wichtiger ist, der Umfang des Geschäftscodes, der zum Testen geschrieben und insbesondere neu geschrieben werden muss, verringert wird .
¹ Sei n sein die maximale Länge eines Strings . Wir können
SayHello
eine Zeichenkette der Länge n - 1 aufrufen und als Referenz übergeben, was gut funktionieren sollte. BeiConsole.WriteLine
Schritt sollte die Formatierung nun mit einer Zeichenfolge der Länge n + 8 enden , was zu einer Ausnahme führt. Möglicherweise führt aufgrund der Speicherbeschränkungen sogar eine Zeichenfolge mit n / 2 Zeichen zu einer Ausnahme. Die Frage, die man sich stellen sollte, ist, ob dieser vierte Test ein Komponententest ist (er sieht aus wie einer, kann jedoch im Vergleich zu durchschnittlichen Komponententests eine viel größere Auswirkung auf die Ressourcen haben) und ob er den tatsächlichen Code oder das zugrunde liegende Framework testet.quelle
personName
in a pasststring
, aber der Wert vonpersonName
plus der Überlauf verketteter Wertestring
.As a rule of thumb, if you remove a unit test, the branch coverage should decrease.
Wenn ich alle vier oben genannten Tests schreibe und dann den dritten Test entferne, verringert sich dann die Abdeckung?Ich halte es für wichtig, zwischen zwei Arten von Teststrategien zu unterscheiden: Komponententests und Integrations- / Akzeptanztests.
In einigen Fällen ist ein Komponententest erforderlich, der jedoch häufig hoffnungslos übertrieben wird. Dies wird durch bedeutungslose Kennzahlen, die den Entwicklern auferlegt werden, wie "100% ige Abdeckung", noch verstärkt. http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf liefert hierfür ein überzeugendes Argument. Berücksichtigen Sie die folgenden Probleme bei aggressiven Komponententests:
Integrations- / Akzeptanztests sind hingegen ein äußerst wichtiger Bestandteil der Softwarequalität, und meiner Erfahrung nach sollten Sie viel Zeit darauf verwenden, sie richtig zu machen.
Viele Geschäfte haben das TDD kool-aid getrunken, aber wie der obige Link zeigt, zeigen einige Studien, dass sein Nutzen nicht schlüssig ist.
quelle
.equals()
Methoden, die von Eclipse generiert wurden, nicht mehr testen müssen ". Ich habe ein Testgeschirr fürequals()
undcompareTo()
github.com/GlenKPeterson/TestUtils geschrieben. Fast jede Implementierung, die ich jemals getestet habe, fehlte. Wie verwenden Sie Sammlungen , wennequals()
undhashCode()
funktionieren nicht richtig zusammen und effizient? Ich feuere den Rest Ihrer Antwort noch einmal an und habe dafür gestimmt. Ich gebe sogar zu, dass einige automatisch generierte equals () -Methoden möglicherweise nicht getestet werden müssen, aber ich hatte so viele Fehler mit schlechten Implementierungen, dass ich nervös werde.Kann nicht verallgemeinert werden.
Wenn ich eine Formel oder einen Algorithmus aus dem physisch basierten Rendern implementieren muss, kann es sehr gut sein, dass ich 10 Stunden mit paranoiden Einheitentests verbringe, da ich weiß, dass der kleinste Fehler oder die geringste Ungenauigkeit dazu führen kann, dass Fehler Monate später kaum zu diagnostizieren sind .
Wenn ich nur einige Codezeilen logisch gruppieren und ihr einen Namen geben möchte, der nur im Dateibereich verwendet wird, kann ich ihn möglicherweise gar nicht testen (wenn Sie darauf bestehen, Tests für jede einzelne Funktion zu schreiben, greifen Programmierer möglicherweise ausnahmslos zurück so wenig Funktionen wie möglich zu schreiben).
quelle
Ja, es ist normal, wenn Sie über TDDing sprechen. Bei automatisierten Tests stellen Sie das gewünschte Verhalten Ihres Codes sicher. Wenn Sie Ihre Tests zuerst schreiben, stellen Sie fest, ob der vorhandene Code bereits das gewünschte Verhalten aufweist.
Das bedeutet, dass:
(Dies gilt nicht für Code-Refactoring, das darauf abzielt, weniger Zeit für das Schreiben des nachfolgenden Codes zu verwenden. Es wird durch Test-Refactoring ausgeglichen, das darauf abzielt, weniger Zeit für das Schreiben der nachfolgenden Tests zu verwenden.)
Ja, auch wenn Sie darüber reden, Tests nachträglich zu schreiben, werden Sie mehr Zeit damit verbringen:
Dann müssen Sie tatsächlich Code schreiben.
Also ja, es ist eine erwartete Maßnahme.
quelle
Ich finde es das Wichtigste.
Beim Unit-Testing geht es nicht immer darum, zu sehen, ob es richtig funktioniert, sondern darum, zu lernen. Sobald Sie etwas ausreichend getestet haben, wird es in Ihrem Gehirn "hartcodiert", und Sie verkürzen schließlich die Zeit für das Testen von Einheiten und können ganze Klassen und Methoden schreiben, ohne etwas zu testen, bis Sie fertig sind.
Aus diesem Grund wird in einer der anderen Antworten auf dieser Seite erwähnt, dass in einem "Kurs" 90% der Tests durchgeführt wurden, weil jeder die Einschränkungen seines Ziels erlernen musste.
Unit-Tests sind nicht nur eine sehr wertvolle Nutzung Ihrer Zeit, da sie Ihre Fähigkeiten buchstäblich verbessern. Sie sind auch eine gute Möglichkeit, Ihren eigenen Code noch einmal durchzugehen und dabei einen logischen Fehler zu finden.
quelle
Es kann für viele Menschen sein, aber es kommt darauf an.
Wenn Sie zuerst Tests schreiben (TDD), kann es vorkommen, dass sich die für das Schreiben des Tests aufgewendete Zeit zum Schreiben des Codes überschneidet. Erwägen:
Wenn Sie Tests nach dem Schreiben des Codes schreiben, stellen Sie möglicherweise fest, dass Ihr Code nicht leicht testbar ist. Daher ist das Schreiben von Tests schwieriger / dauert länger.
Die meisten Programmierer haben viel länger Code geschrieben als Tests, daher würde ich erwarten, dass die meisten von ihnen nicht so fließend sind. Außerdem müssen Sie mehr Zeit aufwenden, um Ihr Test-Framework zu verstehen und zu nutzen.
Ich denke, wir müssen unsere Denkweise dahingehend ändern, wie lange es dauert, Code zu erstellen und wie Unit-Tests durchgeführt werden. Schauen Sie sich das niemals kurzfristig an und vergleichen Sie niemals nur die Gesamtzeit für die Bereitstellung eines bestimmten Features, da Sie nicht nur berücksichtigen müssen, dass Sie besseren / weniger fehlerhaften Code schreiben, sondern auch Code, der einfacher zu ändern und dennoch zu erstellen ist Besser / Weniger Buggy.
Irgendwann sind wir alle nur in der Lage, Code zu schreiben, der so gut ist, dass einige Tools und Techniken nur so viel zur Verbesserung unserer Fähigkeiten beitragen können. Es ist nicht so, dass ich ein Haus bauen könnte, wenn ich nur eine lasergeführte Säge hätte.
quelle
Ja ist es. Mit einigen Einschränkungen.
Erstens ist es "normal" in dem Sinne, dass die meisten großen Läden auf diese Weise funktionieren. Selbst wenn diese Vorgehensweise völlig falsch und dumm war, macht es die Tatsache, dass die meisten großen Läden auf diese Weise funktionieren, dennoch "normal".
Damit meine ich nicht, dass das Testen falsch ist. Ich habe in Umgebungen ohne Tests gearbeitet und in Umgebungen mit Zwangstests, und ich kann Ihnen immer noch sagen, dass selbst die Zwangstests besser waren als keine Tests.
Und ich mache noch kein TDD (wer weiß, ich könnte es in Zukunft tun), aber ich mache die überwiegende Mehrheit meiner Edit-Run-Debug-Zyklen durch Ausführen der Tests, nicht der eigentlichen Anwendung, also arbeite ich natürlich viel auf meine Tests, um so viel wie möglich zu vermeiden, die eigentliche Anwendung ausführen zu müssen.
Beachten Sie jedoch, dass übermäßige Tests und insbesondere der Zeitaufwand für die Wartung der Tests mit Gefahren verbunden sind . (Ich schreibe in erster Linie diese Antwort, um dies ausdrücklich herauszustellen.)
Im Vorwort von Roy Osheroves " The Art of Unit Testing" (Manning, 2009) gibt der Autor zu, an einem Projekt teilgenommen zu haben, das größtenteils aufgrund der enormen Entwicklungsbelastung durch schlecht gestaltete Komponententests, die während des gesamten Berichtszeitraums aufrechterhalten werden mussten, gescheitert war Dauer des Entwicklungsaufwands. Wenn Sie also zu viel Zeit damit verbringen, nichts zu tun, als Ihre Tests beizubehalten, bedeutet dies nicht unbedingt, dass Sie auf dem richtigen Weg sind, denn es ist "normal". Möglicherweise ist Ihre Entwicklungsarbeit in einen fehlerhaften Zustand übergegangen, in dem möglicherweise ein radikales Überdenken Ihrer Testmethode erforderlich ist, um das Projekt zu speichern.
quelle
quelle