Ein erfahrener Entwickler wird niemals Code ohne gründliche Tests veröffentlichen. Unit-Tests sind ein Verfahren, bei dem einzelne, überschaubare Abschnitte eines umfangreicheren Programms geprüft werden.
In diesem Artikel wird detailliert erklärt, wie Sie mit dem Python-Modul Unittest Komponententests für Ihren Code erstellen können. Wir beginnen damit, die verschiedenen Testarten zu unterscheiden.
Im Bereich des Testens unterscheidet man zwischen manuellem und automatisiertem Testen. Manuelle Tests werden von Personen durchgeführt, nachdem die Entwicklung abgeschlossen ist. Automatisierte Tests hingegen werden von Programmen ausgeführt, die die Ergebnisse liefern.
Es liegt auf der Hand, dass manuelles Testen zeitaufwendig und schwerfällig ist. Deshalb schreiben Entwickler Code, um Tests zu automatisieren. Bei den automatisierten Tests gibt es unterschiedliche Kategorien, darunter Unit-Tests, Integrationstests, End-to-End-Tests und Stresstests.
Betrachten wir den typischen Testablauf:
- Code schreiben oder aktualisieren.
- Testfälle für verschiedene Szenarien des Codes schreiben oder aktualisieren.
- Tests ausführen (entweder manuell oder mit einem Test-Runner).
- Testergebnisse analysieren. Bei Fehlern diese beheben und die Schritte wiederholen.
Hier konzentrieren wir uns auf die wichtigste und grundlegendste Testart, die Unit-Tests. Lassen Sie uns ohne Umschweife in das Tutorial einsteigen.
Was sind Unit-Tests?
Unit-Tests sind eine Technik, um einzelne, in sich abgeschlossene Codeabschnitte zu überprüfen. Diese Codeabschnitte sind in der Regel Funktionen. „In sich abgeschlossen“ bedeutet, dass sie keine Abhängigkeiten zu anderen Codeteilen des Projekts aufweisen.
Nehmen wir an, wir müssen untersuchen, ob ein String mit „wdzwdz“ übereinstimmt. Dazu haben wir eine Funktion geschrieben, die einen String als Eingabe akzeptiert und zurückgibt, ob er mit „wdzwdz“ identisch ist.
def ist_gleich_geekflare(string): return string == "wdzwdz"
Diese Funktion hängt von keinem anderen Code ab. Sie kann daher unabhängig getestet werden, indem man unterschiedliche Eingaben verwendet. Solche unabhängigen Codeabschnitte können im gesamten Projekt genutzt werden.
Die Relevanz von Unit-Tests
Grundsätzlich können unabhängige Codeblöcke projektweit eingesetzt werden. Sie müssen daher sorgfältig entwickelt und getestet sein. Unit-Tests sind ideal, um solche unabhängigen Codeblöcke zu überprüfen. Was passiert, wenn wir keine Unit-Tests für unser Projekt verwenden?
Angenommen, wir testen keine kleinen Codeblöcke, die im gesamten Projekt eingesetzt werden. Alle weiteren Tests, wie Integrationstests oder End-to-End-Tests, die auf diesen Codeblöcken aufbauen, können fehlschlagen. Dies kann zu Fehlfunktionen der Anwendung führen. Daher müssen die Grundbausteine des Codes gut geprüft werden.
Nachdem wir die Bedeutung von Unit-Tests erkannt haben, ist es wichtig zu betonen, dass alle unabhängigen Codeblöcke getestet werden sollten. Durch gründliche Unit-Tests wird sichergestellt, dass andere Tests, wie Integrationstests und End-to-End-Tests, nicht aufgrund von Fehlern in den Basisfunktionen fehlschlagen.
In den folgenden Abschnitten werden wir das Python-Unittest-Modul kennenlernen und sehen, wie es zur Erstellung von Unit-Tests in Python verwendet werden kann.
Hinweis: Es wird vorausgesetzt, dass Sie mit Python-Klassen, -Modulen usw. vertraut sind. Sollten Sie mit fortgeschritteneren Konzepten wie Klassen und Modulen nicht vertraut sein, könnten die folgenden Abschnitte schwer zu verstehen sein.
Was ist Python Unittest?
Python Unittest ist ein in Python integriertes Test-Framework zur Überprüfung von Python-Code. Es beinhaltet einen Test-Runner, der das Ausführen von Tests erheblich vereinfacht. So können wir das integrierte Unittest-Modul für Tests nutzen, ohne auf Bibliotheken von Drittanbietern zurückgreifen zu müssen. Die Wahl des Tools hängt jedoch von Ihren spezifischen Anforderungen ab. Das eingebaute Unittest-Modul ist ein guter Ausgangspunkt für Testen in Python.
Um Python-Code mit dem Unittest-Modul zu testen, sind folgende Schritte erforderlich:
#1. Code entwickeln.
#2. Unittest-Modul importieren.
#3. Eine Datei erstellen, deren Name mit „test“ beginnt. Zum Beispiel: test_prime.py. Das Schlüsselwort „test“ dient zur Kennzeichnung der Testdateien.
#4. Eine Klasse erstellen, die von unittest.TestCase erbt.
#5. Methoden (Tests) innerhalb der Klasse definieren. Jede Methode enthält verschiedene Testfälle, die Ihren Anforderungen entsprechen. Die Methodennamen müssen mit dem Schlüsselwort „test“ beginnen.
#6. Tests ausführen. Dies kann auf verschiedenen Wegen erfolgen:
- Befehl: „python -m unittest test_filename.py“.
- Testdateien als gewöhnliche Python-Dateien ausführen mit „python test_filename.py“. Hierzu muss die Hauptmethode von Unittest in der Testdatei aufgerufen werden.
- Verwendung von „discover“: Die Tests können automatisch mit dem Befehl „python -m unittest discover“ ausgeführt werden, ohne den Dateinamen explizit zu nennen. Das System findet die Tests aufgrund der Namenskonvention. Daher ist es wichtig, die Namen der Testdateien mit „test“ zu beginnen.
Beim Testen wird üblicherweise die Ausgabe des Codes mit der erwarteten Ausgabe verglichen. Für diesen Vergleich bietet das Unittest-Modul verschiedene Methoden. Eine Liste dieser Vergleichsfunktionen finden Sie hier.
Die Methoden sind einfach zu verstehen und unkompliziert in ihrer Anwendung.
So viel zur Theorie. Jetzt wollen wir uns dem Programmieren zuwenden.
Hinweis: Bei Fragen zum Unittest-Modul können Sie die Dokumentation konsultieren, um Ihre Unklarheiten zu beseitigen. Lassen Sie uns ohne weitere Verzögerung das Unittest-Modul nutzen.
Komponententests in Python mit Unittest
Wir werden zunächst einige Funktionen erstellen und uns dann auf das Schreiben der Tests konzentrieren. Legen Sie in Ihrem bevorzugten Code-Editor einen neuen Ordner an und erstellen Sie eine Datei mit dem Namen utils.py. Fügen Sie den folgenden Code in die Datei ein:
import math def ist_primzahl(n): if n < 0: return 'Negative Zahlen sind nicht erlaubt' if n <= 1: return False if n == 2: return True if n % 2 == 0: return False for i in range(2, int(math.sqrt(n)) + 1): if n % i == 0: return False return True def kubik(a): return a * a * a def sag_hallo(name): return "Hallo, " + name
In der Datei utils.py haben wir drei Funktionen definiert. Nun müssen wir jede Funktion mit verschiedenen Testfällen prüfen. Beginnen wir mit den Tests für die Funktion ist_primzahl.
#1. Erstellen Sie im gleichen Ordner wie utils.py eine Datei namens test_utils.py.
#2. Importieren Sie die Module utils und unittest.
#3. Erstellen Sie eine Klasse mit dem Namen TestUtils, die von der Klasse unittest.TestCase erbt. Der Name der Klasse ist frei wählbar. Wählen Sie jedoch einen aussagekräftigen Namen.
#4. Definieren Sie innerhalb der Klasse eine Methode namens test_is_prime, die „self“ als Argument akzeptiert.
#5. Schreiben Sie verschiedene Testfälle mit Eingaben für ist_primzahl und vergleichen Sie die Ergebnisse mit den erwarteten Ausgaben.
#6. Beispieltestfall: self.assertFalse(utils.ist_primzahl(1)).
#7. Im obigen Fall erwarten wir, dass die Ausgabe von ist_primzahl(1) „False“ ist.
#8. Ähnlich wie im obigen Fall werden wir weitere Testfälle entwickeln, die auf der zu testenden Funktion basieren.
Betrachten wir die Testfälle:
import unittest import utils class TestUtils(unittest.TestCase): def test_is_prime(self): self.assertFalse(utils.ist_primzahl(4)) self.assertTrue(utils.ist_primzahl(2)) self.assertTrue(utils.ist_primzahl(3)) self.assertFalse(utils.ist_primzahl(8)) self.assertFalse(utils.ist_primzahl(10)) self.assertTrue(utils.ist_primzahl(7)) self.assertEqual(utils.ist_primzahl(-3), "Negative Zahlen sind nicht erlaubt") if __name__ == '__main__': unittest.main()
Wir rufen die Hauptmethode unittest des Moduls auf, um die Tests mit dem Befehl „python filename.py“ auszuführen. Führen Sie nun die Tests durch.
Sie sollten eine Ausgabe sehen, die der folgenden ähnelt:
$ python test_utils.py . ---------------------------------------------------------------------- Ran 1 test in 0.001s OK
Versuchen Sie nun, Testfälle für die anderen Funktionen zu schreiben. Überlegen Sie sich verschiedene Szenarien für die Funktionen und schreiben Sie die entsprechenden Tests. Hier sind weitere Tests, die der oben genannten Klasse hinzugefügt wurden:
... class TestUtils(unittest.TestCase): def test_is_prime(self): ... def test_cubic(self): self.assertEqual(utils.kubik(2), 8) self.assertEqual(utils.kubik(-2), -8) self.assertNotEqual(utils.kubik(2), 4) self.assertNotEqual(utils.kubik(-3), 27) def test_say_hello(self): self.assertEqual(utils.sag_hallo("wdzwdz"), "Hallo, wdzwdz") self.assertEqual(utils.sag_hallo("Chandan"), "Hallo, Chandan") self.assertNotEqual(utils.sag_hallo("Chandan"), "Hi, Chandan") self.assertNotEqual(utils.sag_hallo("Hafeez"), "Hi, Hafeez") ...
Wir haben nur einige der Vergleichsfunktionen des Unittest-Moduls verwendet. Die vollständige Liste finden Sie hier.
Wir haben gelernt, wie man Unit-Tests mit dem Unittest-Modul erstellt. Nun sehen wir uns die verschiedenen Möglichkeiten zur Ausführung der Tests an.
Methoden zur Ausführung von Tests mit Unittest
Wir haben bereits eine Möglichkeit zur Ausführung der Tests kennengelernt. Hier sind zwei weitere Möglichkeiten, um Tests mit dem Unittest-Modul auszuführen:
#1. Verwendung des Dateinamens und des Unittest-Moduls.
Bei dieser Methode verwenden wir das Unittest-Modul und den Dateinamen, um die Tests zu starten. Der Befehl lautet „python -m unittest filename.py“. In unserem Fall lautet der Befehl zur Ausführung der Tests „python -m unittest test_utils.py“.
#2. Verwendung der Discover-Methode
Wir verwenden die Discover-Methode des Unittest-Moduls, um alle Testdateien automatisch zu identifizieren und auszuführen. Für die automatische Erkennung müssen die Dateinamen mit „test“ beginnen.
Der Befehl zum Ausführen der Tests mit der Discover-Methode ist „python -m unittest discover“. Dieser Befehl findet alle Dateien, deren Namen mit „test“ beginnen, und führt diese aus.
Fazit 👩💻
Unit-Tests sind eine wesentliche Komponente in der Welt der Programmierung. Es gibt viele andere Testmethoden in der Praxis. Versuchen Sie, diese nacheinander zu erlernen. Ich hoffe, dieses Tutorial hilft Ihnen beim Schreiben von grundlegenden Tests in Python mit dem Unittest-Modul. Es gibt alternative Bibliotheken von Drittanbietern, wie pytest, Robot Framework, nose, nose2 oder tox, die Sie je nach Ihren Projektanforderungen evaluieren können.
Viel Spaß beim Testen 😎
Vielleicht interessieren Sie sich auch für Python-Interviewfragen und -antworten.