Dies könnte eine ziemlich dumme Frage sein, da ich bei meinen ersten TDD-Versuchen bin. Ich mochte das Gefühl des Vertrauens und die allgemein bessere Struktur meines Codes, aber als ich anfing, es auf etwas anzuwenden, das größer war als ein einziges Spielzeugbeispiel, stieß ich auf Schwierigkeiten.
Angenommen, Sie schreiben eine Art Bibliothek. Sie wissen, was es zu tun hat, Sie wissen allgemein, wie es implementiert werden soll (in Bezug auf die Architektur), aber Sie "entdecken" immer wieder, dass Sie während des Codierens Änderungen an Ihrer öffentlichen API vornehmen müssen. Vielleicht müssen Sie diese private Methode in ein Strategiemuster umwandeln (und jetzt müssen Sie in Ihren Tests eine verspottete Strategie bestehen), vielleicht haben Sie hier und da eine Verantwortung verlegt und eine vorhandene Klasse aufgeteilt.
Wenn Sie vorhandenen Code verbessern, scheint TDD wirklich gut zu passen, aber wenn Sie alles von Grund auf neu schreiben, ist die API, für die Sie Tests schreiben, ein bisschen "verschwommen", es sei denn, Sie machen ein großes Design im Vorfeld. Was tun Sie, wenn Sie bereits 30 Tests für die Methode durchgeführt haben, deren Signatur (und für diesen Teil das Verhalten) geändert wurde? Das ist eine Menge Tests, die sich ändern müssen, wenn sie sich summieren.
Antworten:
Was Sie "großes Design im Vorfeld" nennen, nenne ich "vernünftige Planung Ihrer Klassenarchitektur".
Aus Komponententests lässt sich keine Architektur entwickeln. Sogar Onkel Bob sagt das.
http://s3.amazonaws.com/hanselminutes/hanselminutes_0171.pdf , Seite 4
Ich denke, es wäre sinnvoller, sich TDD aus der Perspektive der Validierung Ihres strukturellen Entwurfs zu nähern . Woher wissen Sie, dass das Design falsch ist, wenn Sie es nicht testen? Und wie überprüfen Sie, ob Ihre Änderungen korrekt sind, ohne auch die ursprünglichen Tests zu ändern?
Software ist "soft", weil sie Änderungen unterworfen ist. Wenn Sie sich in Bezug auf das Ausmaß der Änderungen nicht sicher sind, sollten Sie weiterhin Erfahrung mit Architekturdesign sammeln, und die Anzahl der Änderungen, die Sie an Ihren Anwendungsarchitekturen vornehmen müssen, nimmt im Laufe der Zeit ab.
quelle
Wenn Sie TDD machen. Sie können die Signatur und das Verhalten nicht ändern, ohne sie durch Tests gesteuert zu haben. Daher wurden die 30 fehlgeschlagenen Tests entweder gelöscht oder zusammen mit dem Code geändert / umgestaltet. Oder sie sind jetzt veraltet und sicher zu löschen.
Sie können das 30-fache Rot in Ihrem Rot-Grün-Refaktor-Zyklus nicht ignorieren?
Ihre Tests sollten zusammen mit Ihrem Produktionscode überarbeitet werden. Wenn Sie es sich leisten können, führen Sie alle Tests nach jeder Änderung erneut durch.
Haben Sie keine Angst, TDD-Tests zu löschen. Bei einigen Tests werden Bausteine getestet, um das gewünschte Ergebnis zu erzielen. Auf funktionaler Ebene kommt es auf das gewünschte Ergebnis an. Tests zu Zwischenschritten in dem von Ihnen gewählten / erfundenen Algorithmus können von großem Wert sein oder auch nicht, wenn es mehr als einen Weg gibt, um zum Ergebnis zu gelangen, oder Sie anfangs in eine Sackgasse geraten sind.
Manchmal können Sie einige anständige Integrationstests erstellen, diese beibehalten und den Rest löschen. Es hängt ein wenig davon ab, ob Sie von innen nach außen oder von oben nach unten arbeiten und wie viele Schritte Sie unternehmen.
quelle
Wie Robert Harvey gerade sagte, versuchen Sie wahrscheinlich, TDD für etwas zu verwenden, das von einem anderen konzeptionellen Tool behandelt werden sollte (dh "Design" oder "Modellierung").
Versuchen Sie, Ihr System auf eine recht abstrakte ("allgemeine", "vage") Weise zu entwerfen (oder "modellieren"). Wenn Sie zum Beispiel ein Auto modellieren müssen, müssen Sie nur eine Auto-Klasse mit einer vagen Methode und einem vagen Feld wie startEngine () und int places haben. Das heißt: Beschreiben Sie, was Sie der Öffentlichkeit zugänglich machen möchten, und nicht, wie Sie es implementieren möchten. Versuchen Sie, nur grundlegende Funktionen (Lesen, Schreiben, Starten, Stoppen usw.) verfügbar zu machen, und lassen Sie den Client-Code ausführlich (prepareMyScene (), killTheEnemy () usw.).
Schreiben Sie Ihre Tests unter der Annahme dieser einfachen öffentlichen Schnittstelle auf.
Ändern Sie das interne Verhalten Ihrer Klassen und Methoden nach Bedarf.
Wenn Sie Ihre öffentliche Benutzeroberfläche und Ihre Testsuite ändern müssen, denken Sie nach. Dies ist höchstwahrscheinlich ein Zeichen dafür, dass in Ihrer API und in Ihrem Design / Ihrer Modellierung etwas nicht stimmt.
Es ist nicht ungewöhnlich, eine API zu ändern. Die meisten Systeme in der Version 1.0 warnen die Programmierer / Benutzer ausdrücklich vor möglichen Änderungen in ihrer API. Trotzdem ist ein kontinuierlicher, unkontrollierter Fluss von API-Änderungen ein klares Zeichen für ein schlechtes (oder völlig fehlendes) Design.
Übrigens: Normalerweise sollten Sie nur eine Handvoll Tests pro Methode durchführen. Eine Methode sollte per Definition eine klar definierte "Aktion" für irgendeine Art von Daten implementieren. In einer perfekten Welt sollte dies eine einzelne Aktion sein, die einem einzelnen Test entspricht. In der realen Welt ist es nicht ungewöhnlich (und nicht falsch), wenige unterschiedliche "Versionen" derselben Aktion und wenige unterschiedliche entsprechende Tests zu haben. Sie sollten auf jeden Fall vermeiden, 30 Tests mit derselben Methode durchzuführen. Dies ist ein klares Zeichen dafür, dass die Methode versucht, zu viel zu tun (und der interne Code außer Kontrolle gerät).
quelle
Ich betrachte es aus der Sicht des Benutzers. Wenn ich beispielsweise mit Ihren APIs ein Person-Objekt mit Name und Alter erstellen kann, sollte es für Name und Alter einen Person-Konstruktor (Zeichenfolgenname, int age) und Zugriffsmethoden geben. Es ist einfach, Testfälle für neue Personen mit und ohne Namen und Alter zu erstellen.
doug
quelle