Was ist testgetriebene Entwicklung (TDD)?

large__8282043567Testgetriebene Entwicklung ist ein Prozess, der auf der Wiederholung eines sehr kurzen Entwicklungszyklus beruht. Es basiert auf dem Test-First-Konzept von Extreme Programming (XP), das einfaches Design mit einem hohen Maß an Vertrauen fördert.

Das Verfahren zum Ausführen von TDD folgt:

  1. Schreiben Sie einen Test
  2. Führen Sie alle Tests aus
  3. Schreiben Sie den Implementierungscode
  4. Führen Sie alle Tests aus
  5. Refactor

Dieses Verfahren wird oft als Red-Green-Refactor bezeichnet.

Beim Schreiben von Tests befinden wir uns im roten Zustand. Da test vor der eigentlichen Implementierung geschrieben wird, soll es fehlschlagen. Wenn nicht, ist der Test falsch. Es beschreibt etwas, das bereits existiert oder falsch geschrieben wurde. Beim Schreiben von Tests grün zu sein, ist ein Zeichen für falsch positiv. Solche Tests sollten entfernt oder umgestaltet werden.

Als nächstes kommt der grüne Zustand. Wenn die Implementierung des letzten Tests abgeschlossen ist, sollten alle Tests bestanden werden. Wenn nicht, ist die Implementierung falsch und sollte korrigiert werden.

Die Idee ist nicht, die Implementierung endgültig zu machen, sondern gerade genug Code bereitzustellen, damit Tests bestanden werden können. Sobald alles grün ist, können wir den vorhandenen Code umgestalten. Das bedeutet, dass wir den Code optimaler gestalten, ohne neue Funktionen einzuführen. Während des Refactorings sollten alle Tests die ganze Zeit bestanden werden. Wenn einer von ihnen fehlschlägt, hat Refactor eine vorhandene Funktionalität beschädigt. Refactoring sollte keine neuen Tests enthalten.

Geschwindigkeit ist der Schlüssel

large_5836417589
Ich neige dazu, TDD als eine Partie Tischtennis (oder Tischtennis) zu sehen. Das Spiel ist sehr schnell. Gleiches gilt für TDD. Ich neige dazu, nicht mehr als eine Minute auf beiden Seiten des Tisches zu verbringen (Test und Implementierung). Schreiben Sie einen kurzen Test und führen Sie ihn aus (Ping), schreiben Sie die Implementierung und führen Sie alle Tests aus (Pong), schreiben Sie einen weiteren Test (Ping), schreiben Sie die Implementierung dieses Tests (Pong), refaktorieren Sie und bestätigen Sie, dass alle Tests bestanden sind (Score), wiederholen. Ping, Pong, Ping, Pong, Ping, Pong, Score, wieder dienen. Versuchen Sie nicht, den perfekten Code zu erstellen. Versuchen Sie stattdessen, den Ball am Rollen zu halten, bis Sie denken, dass die Zeit reif ist, um ein Tor zu erzielen (Refactor).

Es geht nicht darum,

T in TDD zu testen, wird oft missverstanden. TDD ist die Art, wie wir uns dem Design nähern. Es ist der Weg, uns zu zwingen, über die Implementierung nachzudenken, bevor wir den Code schreiben. Es ist der Weg, den Code besser zu strukturieren. Das bedeutet nicht, dass Tests, die sich aus der Verwendung von TDD ergeben, nutzlos sind. Weit gefehlt. Sie sind sehr nützlich und ermöglichen es uns, uns schnell zu entwickeln, ohne Angst zu haben, dass etwas kaputt geht. Dies gilt insbesondere dann, wenn Refactoring stattfindet. In der Lage zu sein, den Code neu zu organisieren und gleichzeitig darauf zu vertrauen, dass keine Funktionalität unterbrochen wird, erhöht die Qualität des Codes erheblich.

Das Hauptziel von TDD ist das Codedesign mit Tests als sehr nützliches Nebenprodukt.

Mocking

Damit Tests schnell ablaufen und ein konstantes Feedback geben, muss der Code so organisiert sein, dass Methoden, Funktionen und Klassen leicht verspottet und gestoppt werden können. Geschwindigkeit der Ausführung wird es stark beeinträchtigt werden, zum Beispiel müssen unsere Tests mit der Datenbank zu kommunizieren. Indem wir externe Abhängigkeiten verspotten, können wir diese Geschwindigkeit drastisch erhöhen. Die Ausführung der gesamten Unit-Tests-Suite sollte in Minuten, wenn nicht in Sekunden gemessen werden. Wichtiger als die Geschwindigkeit ist, dass das Entwerfen des Codes so, dass er leicht verspottet und gestopft werden kann, uns zwingt, diesen Code besser zu strukturieren, indem wir die Trennung von Bedenken anwenden. Mit oder ohne Mocks sollte der Code so geschrieben werden, dass wir beispielsweise eine Datenbank leicht durch eine andere ersetzen können. Das „andere“ kann zum Beispiel verspottet oder In-Memory-Datenbank.

Ein Beispiel für das Verspotten in Scala finden Sie im Artikel Scala Test-Driven Development (TDD): Unit Testing File Operations with Specs2 and Mockito . Wenn Ihre Programmiersprache nicht Scala ist, kann article dennoch sehr nützlich sein, um das Muster zu sehen, das auf jede Sprache angewendet werden kann.

Beobachter

Sehr nützliches Werkzeug bei der Arbeit in der TDD-Mode sind Beobachter. Sie sind Frameworks oder Tools, die ausgeführt werden, bevor wir mit der Arbeit beginnen und auf Änderungen im Code achten. Wenn eine solche Änderung erkannt wird, werden alle Tests ausgeführt. Im Falle von JavaScript erlauben dies fast alle Build-Systeme und Task-Runner. Schluck (mein Favorit) und Grunzen sind zwei von vielen Beispielen. Scala hat sbt-Revolver (unter anderem). Die meisten anderen Programmiersprachen verfügen über ähnliche Tools, die (falls erforderlich) neu kompilieren und alle (oder betroffenen) Tests ausführen, wenn sich der Code ändert. Ich habe immer meinen Bildschirm in zwei Fenster aufgeteilt. Einer mit dem Code, an dem ich arbeite, und der andere mit Ergebnissen von Tests, die kontinuierlich ausgeführt werden. Ich muss nur darauf achten, dass die Ausgabe dieser Beobachter der Phase entspricht, in der ich mich befinde (rot oder grün).

Dokumentation

Ein weiterer sehr nützlicher Nebeneffekt von TDD (und gut strukturierten Tests im Allgemeinen) ist die Dokumentation. In den meisten Fällen ist es viel einfacher, anhand von Tests herauszufinden, was der Code tut, als die Implementierung selbst. Ein weiterer Vorteil, den andere Dokumentationstypen nicht bieten können, besteht darin, dass Tests niemals veraltet sind. Wenn eine Diskrepanz zwischen Tests und dem Implementierungscode besteht, schlagen Tests fehl. Fehlgeschlagene Tests bedeuten ungenaue Dokumentation.

Tests als Dokumentation Der Artikel bietet eine etwas tiefere Begründung für die Verwendung von Tests anstelle der herkömmlichen Dokumentation.

Zusammenfassung

Meiner Erfahrung nach ist TDD wahrscheinlich das wichtigste Werkzeug, das wir in unserer Software-Toolbox haben. Es braucht viel Zeit und Geduld, um TDD zu beherrschen, aber sobald diese Kunst beherrscht ist, steigen Produktivität und Qualität drastisch. Der beste Weg, TDD zu lernen und zu üben, ist die Kombination mit Pair Programming. Wie bei einem Ping-Pong-Spiel, für das zwei Teilnehmer erforderlich sind, kann TDD paarweise ausgeführt werden, wobei ein Codierer Tests und der andere die Implementierung dieser Tests schreibt. Rollen können nach jedem Test wechseln (wie es oft in Codierungs-Dojos gemacht wird).

Probieren Sie es aus und geben Sie nicht auf, wenn Sie mit Hindernissen konfrontiert werden, da es viele geben wird.

Test Driven Development (TDD): Best Practices Mit Java-Beispielen ist ein guter Ausgangspunkt. Obwohl es Java-Beispiele verwendet, können die gleichen, wenn nicht alle, Praktiken auf jede Programmiersprache angewendet werden. Ein Beispiel in Java (wie im vorherigen Fall ist es leicht auf andere Sprachen anwendbar) finden Sie im Artikel TDD Example Walkthrough .

Ein weiterer guter Weg zur Perfektion TDD Fähigkeiten sind Code Katas (es gibt viele auf dieser Seite).

Was sind Ihre Erfahrungen mit TDD? Es gibt so viele Variationen, wie es Teams gibt, die es üben, und ich würde gerne von Ihren Erfahrungen hören.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.