Kurs
Tests geben dir die Sicherheit, dass dein Code das tut, was er soll. In diesem Tutorial lernst du die Grundlagen der testgetriebenen Entwicklung (TDD) mit Python. Zuerst klären wir kurz, was testgetriebene Entwicklung ist und warum es hilft, Tests vor dem Code zu schreiben. Wir verfolgen einen Test-First-Ansatz: Wir schreiben zunächst fehlgeschlagene Testfälle für die gewünschte Funktionalität und implementieren erst danach die eigentlichen Funktionen.
Voraussetzungen
Für dieses Tutorial solltest du grundlegende Python-Kenntnisse mitbringen. Falls du dein Wissen auffrischen willst, schau dir diesen Kurs an: Introduction to Python for Developers.
Ein Test-First-Ansatz hilft dir, über das gewünschte Verhalten und erwartete Ausgaben nachzudenken. In Python kannst du mit verschiedenen Bibliotheken testen, etwa pytest und unittest. Wir konzentrieren uns hier jedoch auf einfache Testfälle mit nativem Python, die prüfen, ob die gewünschte Funktionalität die erwartete Ausgabe liefert.
Wir starten mit einem einfachen Testfall und erweitern ihn schrittweise, um verschiedene Szenarien abzudecken. Währenddessen entdecken wir möglicherweise Bugs oder Lücken in der ersten Implementierung, die wir verbessern müssen. Dieses iterative Vorgehen – anspruchsvollere Tests schreiben, sie scheitern sehen und dann die Implementierung verbessern – steht im Kern der testgetriebenen Entwicklung mit Python.
Für dieses Tutorial nutzen wir DataLab, DataCamps cloudbasiertes Daten-Notebook, in dem du Python ohne lokale Installation schreiben und ausführen kannst. Los geht’s!
Erste Schritte mit DataLab
Bevor wir mit testgetriebener Entwicklung starten, schauen wir uns DataLab an und wie es dich beim Lernen unterstützt. Öffnest du DataLab, findest du viele Optionen. Für den Moment konzentrieren wir uns darauf, Python in DataLab zu schreiben.

Wenn du Python auswählst, öffnet das Workbook eine Codezelle, in der du Python schreiben kannst. Das sieht etwa so aus:

Hier gibt es einige praktische Optionen. Du kannst die Zelle ausführen, um Ausgaben zu erzeugen, Kommentare oder Notizen für dein Lernen hinzufügen und KI nutzen, um den Einstieg zu erleichtern oder Blockaden zu lösen. Außerdem kannst du so viele Zellen hinzufügen oder löschen, wie du brauchst. Wir konzentrieren uns auf das Ausführen der Zelle über die Option "Run". Wie du im Code unten siehst, wird jede Ausgabe deines Codes beim Ausführen direkt unter der Zelle protokolliert.
Kurz notiert: Wenn du mehrere Zellen nutzt und in einer Zelle eine Variable definierst, sie aber in einer anderen Zelle verwenden willst, musst du jede Zelle einzeln ausführen oder das gesamte Workbook starten (über den "Run"-Button oben rechts in deinem Workbook).

Jetzt, da die DataLab-Basics sitzen, starten wir mit testgetriebener Entwicklung.
Testgetriebene Entwicklung
Testgetriebene Entwicklung bedeutet, Tests zu schreiben, bevor du den Code schreibst. Um TDD zu erklären, beginnen wir mit einem einfachen Beispiel: ein Python-Skript, das Zahlen addiert. Bevor wir die Funktion schreiben, erstellen wir einen Test, der prüft, ob 1 + 1 gleich 2 ist. Das kannst du mit nativem Python so umsetzen:
assert 1 + 1 == 2
Das Schlüsselwort assert in Python dient dazu, Testfälle zu formulieren und zu prüfen, ob Bedingungen im Programm True ergeben. So kannst du Verhalten und Ausgaben deines Codes validieren. Schlägt ein assert fehl, wird ein AssertionError ausgelöst – ein Hinweis auf ein Problem im Code. In deinem DataLab-Workbook sieht das so aus:

Beispiel 1: Eine einfache Funktion testen
Starten wir mit der Testfunktion. Öffne in DataLab eine Python-Datei. Testgetriebene Entwicklung beginnt mit einem fehlgeschlagenen Test. Schreiben wir also einen fehlschlagenden Test, indem wir die Funktion add() aufrufen, die noch nicht definiert ist.
assert add(1, 1) == 2
Das führt zu einem NameError, der anzeigt, dass es noch keine Implementierung gibt – der sogenannte "Red"-Schritt. Ein NameError tritt auf, wenn du eine Funktion oder Variable aufrufst, die nicht definiert wurde.

Jetzt implementieren wir die Funktion. Das geht, indem wir sie definieren:
def add(num1, num2):
return
Wir haben unsere Funktion add definiert, die zwei Parameter entgegennimmt: num1 und num2. Unsere Funktion gibt noch nichts zurück. Schauen wir, ob diese Implementierung unseren Test besteht!

Ein NameError erscheint nicht mehr. Beim Ausführen tritt jedoch weiterhin ein Fehler auf – diesmal ein AssertionError. Der Test ist also immer noch fehlgeschlagen! Warum? Weil unsere Funktion noch keinen Rückgabewert hat.
Beim Test kommt es zum AssertionError, weil 1 + 1 mit unserer leeren Implementierung nicht 2 ergibt. Jetzt bringen wir den Test zum Grünen, indem wir die Logik korrekt implementieren.

Du siehst den grünen Punkt in der Ecke der Zelle. Er zeigt an, dass dein Code gültig ist und der Lauf erfolgreich war. Zuvor war er rot mit einem Laufzeitfehler, und der Fehlertyp wurde unter der Zelle angezeigt. Das ist beim Debuggen in DataLab sehr hilfreich.
Du hast soeben deinen ersten Test in Python mit testgetriebener Entwicklung geschrieben. Gut gemacht! Als Nächstes erweitern wir unsere Tests und überlegen, wie wir potenzielle Fehlerfälle abfangen, die dazu führen könnten, dass unsere Funktion scheitert oder nicht die erwartete Ausgabe liefert.
Beispiel 2: Mehrere Testfälle
Mit nur einem Eingabewert zu testen, deckt mögliche Fehler oft nicht auf. Bugs verstecken sich leicht – besonders, wenn deine Funktion auf variablen Nutzereingaben oder externer Logik basiert. Wie testen wir eine Funktion also gründlich gegen mehrere Werte?
Was passiert zum Beispiel, wenn der Funktion ein falscher Datentyp übergeben wird? Du könntest Python-Testframeworks nutzen, aber bleiben wir hier bei einfachem Python. Zuerst definiere ich eine Liste aus Eingabe-Dictionaries, um verschiedene Nutzungsszenarien zu simulieren:
test_cases = [
{"num1": 1, "num2": 3, "expected": 4},
{"num1": 1, "num2": "invalid", "expected": "Error: num2 must be a number"},
{"num1": [1,2,3], "num2": 2, "expected": "Error: num1 must be a number"},
{"num1": -1, "num2": 1, "expected": 0},
{"num1": 3.5, "num2": 2.5, "expected": 6.0},
{"num1": 100, "num2": 200, "expected": 300}
]
Der Code oben zeigt Eingaben für die Funktion samt erwarteten Ausgaben. Wir müssen unseren Test jedoch anpassen, um über diese Testfälle zu iterieren. Dazu verschachteln wir das assert in einer for-Schleife und validieren jedes Dictionary in der Liste.
for test in test_cases:
assert add(test["num1"], test["num2"]) == test["expected"]
Da sich die Funktion nicht geändert hat: Würden wir erwarten, dass dieser Test besteht oder fällt er durch? Und welcher Fehler könnte auftreten?

Der Test wirft einen TypeError, weil wir Nicht-Zahlen nicht behandeln. Was, wenn statt eines int ein String oder Boolean übergeben wird? Diese Fälle können wir in der Funktion abfangen! Indem wir prüfen, ob die Eingabe ein Integer oder Float ist, geben wir bei ungültigen Typen eine passende Meldung zurück.
def add(num1, num2):
if type(num1) is not int and type(num1) is not float:
return "Error: num1 must be a number"
elif type(num2) is not int and type(num2) is not float:
return "Error: num2 must be a number"
else:
return num1 + num2
Wenn wir die Tests erneut ausführen, erhalten wir keine Fehler mehr – unsere Tests sind bestanden. Der grüne Kreis zeigt an, dass wir jetzt erfolgreiche Tests implementiert haben. Stark!

Fazit
In diesem Tutorial haben wir die Grundlagen der testgetriebenen Entwicklung in Python mit DataLab behandelt. DataLab bietet eine Cloud-IDE, in der du Python ohne lokale Installation schreiben und ausführen kannst. Tests validieren das Verhalten deines Codes und fangen Fehler frühzeitig ab. Assert-Anweisungen prüfen Bedingungen und lösen bei Fehlschlägen Ausnahmen aus.
Du kannst weitere Testfälle erkunden und in DataLab eigene Tests schreiben! Wenn du mehr über das Testen in Python lernen willst, schau dir unseren DataCamp-Kurs an: Introduction to Testing in Python.
Amina ist Praktikantin für Inhaltsentwicklung bei Datacamp. Mit einem Hintergrund in Architektur und Pädagogik wechselte sie den Beruf, um sich der Softwareentwicklung zu widmen. Sie begann mit JavaScript und konzentriert sich jetzt auf Python.
