[MELDEN] Von der Vision zum Code: Ein Leitfaden zur Ausrichtung der Geschäftsstrategie auf die Ziele der Softwareentwicklung ist veröffentlicht!
HOL ES DIR HIER

Testgetriebene Entwicklung (TDD) — Kurzanleitung [2025]

readtime
Last updated on
February 17, 2025

A QUICK SUMMARY – FOR THE BUSY ONES

TABLE OF CONTENTS

Testgetriebene Entwicklung (TDD) — Kurzanleitung [2025]

Einführung

Dieser Artikel über Test-Driven Development (TDD) hilft Ihnen dabei, sich mit diesem Entwicklungszyklus vertraut zu machen und ihn an Ihre Programmiermethoden anzupassen. Und warum solltest du das tun? Kontinuierliches automatisiertes Testen ist eine der wichtigsten Methoden, mit denen Sie Fehler beheben und Entwicklungsrisiken minimieren können, um eine hervorragende Bereitstellung sicherzustellen. Laut unserem Bericht: „Von der Vision zum Code: Ein Leitfaden zur Ausrichtung der Geschäftsstrategie auf die Ziele der Softwareentwicklung“, sogar 78% der weltweiten CTOs und Technologieführer geben an, dass gute DevOps-Praktiken, einschließlich regelmäßiger Tests, stark oder sehr stark in ihren Entwicklungszyklus integriert sind.

DevOps best practices

Das Konzept der Test-Driven Development (TDD) wurde 2003 von Kent Beck eingeführt. Es gibt keine formale Definition, aber Beck gibt Ansätze und Beispiele für TDD. Das Ziel von TDD ist „schreibe sauberen Code, der funktioniert“.

Folgen Sie in TDD nur einer Faustregel: Ändern Sie nur den Produktionscode wenn jeder Test schlägt fehl. Sonst, nur umgestalten, um den Code zu optimieren. Für aktualisierte Anforderungen konvertieren Sie sie in Testfälle, fügen Sie diese Tests hinzu und schreiben Sie erst dann neuen Code.

TDD ist ein sehr kurzer Entwicklungszyklus und wiederholt sich. Kundenanforderungen werden in hochspezifische Testfälle umgewandelt und die Software wird so geschrieben und verbessert, dass sie die neuen Tests besteht.

Testgetriebene Entwicklung bezieht sich auf Test-First-Programmierkonzepte in extremer Programmierung, Befürwortung häufiger Softwareupdates/-veröffentlichungen in kurzen Entwicklungszyklen und Förderung umfassender Code-Reviews, Komponententests und schrittweiser Hinzufügung von Funktionen.

Ein eng mit TDD verwandtes Konzept ist Acceptance Test-Driven Development (ATDD), bei dem Kunde, Entwickler und Tester alle am Prozess der Anforderungsanalyse beteiligt sind. TDD ist sowohl für Mobilgeräte als auch Entwickler von Web-Apps, wohingegen ATDD ein Kommunikationsinstrument ist, das sicherstellt, dass die Anforderungen klar definiert sind.

Testgetriebener Entwicklungszyklus (TDD)

Test-Driven Development (TDD) cycle.

Beginnen wir mit den Grundlagen und schauen uns den TDD-Zyklus, auch bekannt als Red-Green-Refactor-Prozess, Schritt für Schritt an.

Der testgetriebene Entwicklungszyklus:

1. Füge einen Test hinzu, der sicherlich FEHLSCHLAGEN wird. (Rot)

In TDD wird jede Funktion in einer Software zuerst in Form von Testfällen hinzugefügt. Ein Test wird für eine neue oder aktualisierte Funktion erstellt. Um die Tests schreiben zu können, müssen Entwickler die Funktionsspezifikationen und Anforderungen verstehen.

Diese Praxis unterscheidet TDD von herkömmlichen Softwareentwicklungsmethoden, bei denen Komponententests nach dem Schreiben des Quellcodes geschrieben werden. Auf diese Weise sorgt TDD dafür, dass sich der Entwickler auf die Anforderungen konzentriert vor den Code schreiben.

2. Führen Sie alle Tests durch. Prüfen Sie, ob ein Test fehlschlägt.

Das Ausführen von Tests bestätigt, dass das Testsystem ordnungsgemäß funktioniert, und beweist gleichzeitig, dass neuer Code erforderlich ist, wenn neu hinzugefügte Tests mit dem vorhandenen Code fehlschlagen.

3. Schreiben Sie nur genug Code, um alle Tests zu bestehen. (Grün)

Der neue Code, der in dieser Phase geschrieben wurde, ist möglicherweise nicht perfekt und besteht den Test möglicherweise auf irrelevante Weise. Die einzige Voraussetzung in dieser Phase ist, dass alle Tests bestanden werden. Eine Möglichkeit, mit dem Hinzufügen der Anweisungen zu beginnen, besteht darin, eine Konstante zurückzugeben und schrittweise logische Blöcke hinzuzufügen, um die Funktion zu erstellen.

4. Führen Sie alle Tests durch. Wenn ein Test fehlschlägt, fahren Sie mit Schritt 3 fort. Fahren Sie andernfalls fort.

Wenn alle Tests bestanden sind, kann gesagt werden, dass der Code die Testanforderungen erfüllt und keine vorhandenen Funktionen beeinträchtigt. Wenn ein Test fehlschlägt, muss der Code bearbeitet werden, um sicherzustellen, dass alle Tests bestanden werden.

5. Refaktorisieren Sie den Code. (Refaktorieren)

Wenn die Codebasis wächst, muss sie regelmäßig bereinigt und gewartet werden. Wie? Es gibt ein paar Möglichkeiten:

  • Neuer Code, der der Einfachheit halber hinzugefügt wurde, um einen Test zu bestehen, kann an seine logische Stelle im Code verschoben werden.
  • Doppelarbeit muss vermieden werden.
  • Objektdefinitionen und Namen müssen so festgelegt werden, dass sie ihren Zweck und ihre Verwendung wiedergeben.
  • Je mehr Funktionen hinzugefügt werden, desto länger werden die Funktionen. Es kann sich als vorteilhaft erweisen, es aufzuteilen und sorgfältig zu benennen, um die Lesbarkeit und Wartbarkeit zu verbessern.
  • Da alle Tests während der Refactoring-Phase erneut ausgeführt werden, kann der Entwickler sicher sein, dass der Prozess keine vorhandenen Funktionen verändert.

6. Wenn ein neuer Test hinzugefügt wird, wiederholen Sie den Vorgang ab Schritt 1.

Machen Sie kleine Schritte und zielen Sie darauf ab, zwischen den einzelnen Testläufen nur 1 bis 10 Änderungen vorzunehmen.

Wenn der neue Code einen neuen Test nicht schnell erfüllt oder andere unabhängige Tests unerwartet fehlschlagen, machen Sie den Code rückgängig oder kehren Sie zu einem funktionierenden Code zurück, anstatt ein umfangreiches Debugging durchzuführen.

Bei der Verwendung externer Bibliotheken ist es wichtig, keine so kleinen Inkremente vorzunehmen, dass sie lediglich die Bibliothek selbst testen, es sei denn, es geht darum zu testen, ob die Bibliothek veraltet/inkompatibel, fehlerhaft oder nicht funktionsfähig ist.

Übliche Praktiken im TDD-Zyklus

In diesem Teil gebe ich Ihnen eine kurze Anleitung zu den gängigen TDD-Methoden, die Ihnen helfen wird besser codieren.

Kleine Einheiten

Eine Einheit ist eine Klasse/ein Modul, bei dem es sich um eine Gruppe eng verwandter Funktionen handelt, die oft als Modul. Wenn die Einheiten klein gehalten werden, ergeben sich Vorteile wie einfacheres Testen und Debuggen.

Aufbau testen

Da Sie immer Tests für Einheiten durchführen werden, ist es wichtig, die folgende Teststruktur anzuwenden:

  1. Einrichtung: Das System oder die zu testende Einheit (UUT) in den für die Ausführung der Tests erforderlichen Zustand versetzen und sicherstellen, dass das System für den Test bereit ist.
  2. Hinrichtung: Führen Sie den Test auf dem Ziel aus und überwachen Sie alle Rückgabewerte und Ausgaben, um sicherzustellen, dass der Ausführungspfad der ist, auf den Sie abzielen.
  3. Validierung: Bestätigen/Vergewissern Sie sich, dass die Ergebnisse korrekt sind. Dies ist der Punkt, an dem festgestellt wird, ob der Test bestanden/fehlgeschlagen ist.
  4. Aufräumen: Setzt das Testsystem in den Originalzustand zurück. Dadurch kann sofort ein weiterer Test ausgeführt werden.

Zu vermeidende Praktiken

  • Determinismus — stellen Sie sicher, dass die Tests deterministisch sind. Abhängigkeit Bei Ereignissen wie API-Aufrufen oder Systemdatum/Uhrzeit können Tests auch ohne Codeänderungen fehlschlagen.
  • Vermeiden Sie nach Möglichkeit, eine Ausführungsreihenfolge für Tests zu verlangen, und lassen Sie die zufällige Ausführung von Tests zu. Vermeiden Sie ebenfalls, dass die Tests von früheren oder anderen Testergebnissen abhängen.
  • Testen des genauen Ausführungsverhaltens, des Zeitpunkts oder der Leistung.
  • Entwickeln Sie keine Testfälle, die mehr auswerten, als sie sollten („allwissende Orakel“).
  • Entwerfen Sie keine Tests, deren Ausführung erheblich länger dauert.

Individuelle Praxen

  • Konzentrieren Sie sich bei jedem Test nur auf die Ergebnisse, die zu seiner Validierung erforderlich sind.
  • Entwickeln Sie in Systemen, die nicht in Echtzeit arbeiten, zeitbezogene Tests, um eine Toleranz bei der Ausführung zu gewährleisten. Es ist gängige Praxis, bei verspäteter Ausführung einen Spielraum von 5 bis 10% vorzusehen, um die Wahrscheinlichkeit falsch negativer Ergebnisse während der Tests zu verringern.
  • Behandeln Sie den Testcode genauso wie den Produktionscode. Dies verbessert die Codequalität und Robustheit.
  • Teilen Sie die Tests in kleinere Tests auf, wo immer dies möglich ist.
  • Überprüfe als Team deine Tests und Testpraktiken, um effektive Techniken auszutauschen und schlechte Angewohnheiten zu erkennen.

Fortgeschrittene Praktiken

Acceptance Test Driven Development (ATDD) verfügt über fortschrittliche TDD-Praktiken, und das Entwicklungsteam hat das Ziel, die vom Kunden definierten Abnahmetests zu erfüllen. Der Kunde verfügt möglicherweise über einen automatisierten Mechanismus, um zu entscheiden, ob die Software seinen Anforderungen entspricht.

Test-Driven Development (TDD) — Vor- und Nachteile

Leistungen

  • Das Schreiben von Tests in TDD zwingt Sie dazu, über Anwendungsfälle nachzudenken, und verbessert Produktivität.
  • Selbst wenn man bedenkt, dass die Menge an Code, die auf dem Schreiben von Komponententests basiert, wird die gesamte Implementierung kürzer und weniger Buggy (nach einem von Müller und Padberg entwickelten Modell, „Über die Kapitalrendite testgetriebener Entwicklung“).
  • Debuggen wird einfacher.
  • Wenn gängige TDD-Praktiken befolgt werden, ist der entwickelte Code modularisiert, flexibel und erweiterbar.
  • Automatische Regressionserkennung bei jedem inkrementellen Update.
  • Automatisierte Tests sind sehr gründlich. Da nicht mehr Code geschrieben wird, als nötig ist, um die fehlgeschlagenen Tests zu bestehen, decken diese automatisierten Tests in der Regel jeden Codepfad ab.
  • Einfachere Dokumentation, Komponententests dokumentieren sich von selbst und sind leichter zu lesen und zu verstehen. Sie sollten den Quell-/Produktionscode immer beschreibend dokumentieren.

Einschränkungen

  • TDD schneidet nicht gut ab, wenn Funktionstests sind erforderlich, z. B. GUI-Design.
  • Wenn Entwickler die Komponententests selbst schreiben, teilen sich die Tests möglicherweise dieselben blinde Flecken wie der Code.
  • Manchmal kann eine hohe Anzahl von bestandenen Tests zu einem falsches Sicherheitsgefühl, was zu weniger Testaktivitäten während des Integrationstests führt, was möglicherweise zu Problemen führt.
  • Tests werden Teil der Wartungsaufwand. Schlecht geschriebene Tests können außerdem zu höheren Wartungs- oder Aktualisierungskosten führen.
  • Der bei TDD erreichte Detaillierungsgrad kann nicht sein leicht nachzubauen später.

Testgetriebene Entwicklung in der Praxis

Für große Anlagen

Bei großen Systemen ist das Testen eine Herausforderung und erfordert eine modulare Architektur mit genau definierten Komponenten. Einige wichtige Anforderungen, die erfüllt werden müssen, sind:

  • Hohe Kohäsion stellt sicher, dass jedes Modul eine Reihe verwandter Funktionen bietet, sodass die entsprechenden Tests einfacher zu verwalten sind.
  • Niedrige Kopplung ermöglicht das isolierte Testen von Modulen.

Szenario-Modellierung

Bei der Szenariomodellierung wird eine Reihe von Sequenzdiagrammen erstellt, wobei sich jedes Diagramm auf ein einzelnes Ausführungsszenario auf Systemebene konzentriert. Es bietet ein hervorragendes Mittel zur Entwicklung von Interaktionsstrategien als Reaktion auf eine Eingabe.

Jedes Szenariomodell dient als eine Reihe von Anforderungen für die Funktionen, die eine Komponente bereitstellen wird. Die Szenariomodellierung kann bei der Konstruktion von TDD-Tests in komplexen Systemen hilfreich sein.

Sichtbarkeit und Sicherheit des Codes

Es ist wichtig, den Code zwischen Testen und Produktion zu unterscheiden. Die Komponententestsuite muss auf den zu testenden Code zugreifen können. Bei der Gestaltung von Kriterien wie dem Verbergen und Verkapseln von Informationen und der Trennung von Modulen dürfen jedoch keine Kompromisse eingegangen werden.

Beim objektorientierten Design können Tests immer noch nicht auf private Datenelemente und Methoden zugreifen und erfordern zusätzliche Codierung. Alternativ kann eine innere Klasse innerhalb des Quellcodes verwendet werden, um die Komponententests zu enthalten. Solch Test-Hacks sollten nicht bleiben im Produktionscode. TDD-Praktiker argumentieren oft, ob private Daten überhaupt getestet werden sollten.

Test-Driven Development (TDD) step by step.

Fazit

In diesem Artikel haben wir uns einen Überblick über Test-Driven Development (TDD) verschafft. Wir haben die Vor- und Nachteile von TDD sowie die mit TDD verbundenen Praktiken vorgestellt und Ideen behandelt, die man kennen muss, um mit der Einführung des TDD-Zyklus beginnen zu können.

Wenn Sie daran interessiert sind, mehr über die Bedeutung von Test-Driven Development zu erfahren, lesen Sie unbedingt unseren Bericht „Von der Vision zum Code: Ein Leitfaden zur Ausrichtung der Geschäftsstrategie auf die Ziele der Softwareentwicklung“.

Mateusz Konieczny Tech Evangelist Brainhub Quote

Ressourcen:

Frequently Asked Questions

No items found.

Our promise

Every year, Brainhub helps 750,000+ founders, leaders and software engineers make smart tech decisions. We earn that trust by openly sharing our insights based on practical software engineering experience.

Authors

Matt Warcholinski
github
Chief Growth Officer

Ein Serienunternehmer, leidenschaftlicher Forschungs- und Entwicklungsingenieur mit 15 Jahren Erfahrung in der Technologiebranche. Teilt sein Expertenwissen über Technologie, Startups, Geschäftsentwicklung und Marktanalysen.

Matt Warcholinski
github
Chief Growth Officer

Ein Serienunternehmer, leidenschaftlicher Forschungs- und Entwicklungsingenieur mit 15 Jahren Erfahrung in der Technologiebranche. Teilt sein Expertenwissen über Technologie, Startups, Geschäftsentwicklung und Marktanalysen.

Read next

No items found...