目次  
- 1 1. Was ist Python unittest?
- 2 2. Grundlagen der Verwendung von unittest
- 3 3. Verwendung von setUp() und tearDown()
- 4 4. Test von Abhängigkeiten mit Mocks
- 5 5. Ausnahmebehandlung und benutzerdefinierte Assertions
- 6 6. unittest-Test-Discovery-Funktion
- 7 7. Tipps zur Leistungsverbesserung mit unittest
- 8 8. Zusammenfassung und nächste Schritte
1. Was ist Python unittest?
unittest ist ein in der Standardbibliothek von Python enthaltenes Unit‑Test‑Framework und ein wichtiges Werkzeug, um die Code‑Qualität sicherzustellen. Es ermöglicht Entwicklern, einzelne Teile des Codes separat zu testen und so frühzeitig Fehler zu entdecken. Außerdem hilft es während der kontinuierlichen Entwicklung sicherzustellen, dass Änderungen am Code bestehende Funktionen nicht beschädigen.Wichtigkeit von Unit‑Tests
Wenn der Code komplexer wird, wird es schwieriger zu überprüfen, ob die verschiedenen Teile korrekt zusammenarbeiten. Durch die Einführung von Unit‑Tests lässt sich das Auftreten unerwarteter Fehler bei kleinen Änderungen leichter verhindern und die Gesamtstabilität des Programms erhalten.2. Grundlagen der Verwendung von unittest
Die Grundlagen vonunittest bestehen darin, eine Klasse zu erstellen, die unittest.TestCase erbt, und darin Testmethoden zu definieren. In den Testmethoden verwendet man Assertionsmethoden wie assertEqual(), um das erwartete Ergebnis mit dem tatsächlichen Ergebnis zu vergleichen.  Die Grundlagen von unittest bestehen darin, eine Klasse zu erstellen, die von unittest.TestCase erbt, und darin Testmethoden zu definieren. In den Testmethoden verwendet man Assertionsmethoden wie assertEqual(), um das erwartete Ergebnis mit dem tatsächlichen Ergebnis zu vergleichen.Beispiel für einen grundlegenden Test
Der folgende Code ist ein einfaches Beispiel zum Testen der Funktionadd(a, b).import unittest
# Zu testender Code
def add(a, b):
    return a + b
# Testklasse
class TestAddFunction(unittest.TestCase):
    def test_add_integers(self):
        result = add(2, 3)
        self.assertEqual(result, 5)
if __name__ == '__main__':
    unittest.main()add() korrekt funktioniert. Die Methode assertEqual() prüft, ob der erwartete Wert und das tatsächliche Ergebnis gleich sind. Auf diese Weise kann man sicherstellen, dass die Funktion für mehrere Fälle korrekt arbeitet.Erweiterung von Tests
Mit mehreren Testmethoden kann man das Verhalten der Funktion für verschiedene Eingaben testen. Zum Beispiel können Fließkommazahlen oder das Zusammenfügen von Zeichenketten getestet werden.def test_add_floats(self):
    result = add(2.5, 3.5)
    self.assertAlmostEqual(result, 6.0, places=2)
def test_add_strings(self):
    result = add("Hello, ", "World!")
    self.assertEqual(result, "Hello, World!")
3. Verwendung von setUp() und tearDown()
Um bestimmte Vorgänge automatisch vor und nach einem Test auszuführen, verwendet man die MethodensetUp() und tearDown(). Dadurch kann man die erforderlichen Vorbereitungen treffen, bevor der Test ausgeführt wird, und nach dem Test eine Bereinigung durchführen.Beispiel für setUp()
setUp() ist eine Methode, die vor jedem Testmethodenaufruf zwingend aufgerufen wird und es ermöglicht, gemeinsame Initialisierungsschritte zusammenzufassen.def setUp(self):
    self.temp_value = 42Beispiel für tearDown()
tearDown() ist eine Methode, die nach jeder Testmethode ausgeführt wird und Nachbearbeitungen sowie das Freigeben von Ressourcen übernimmt. Sie kann beispielsweise zum Trennen von Datenbankverbindungen oder zum Löschen temporärer Dateien verwendet werden.def tearDown(self):
    self.temp_value = None4. Test von Abhängigkeiten mit Mocks
Wenn der zu testende Code von externen Ressourcen (Datenbank, API usw.) abhängt, kann man die abhängigen Teile durch Mocks ersetzen, um die Ausführungsgeschwindigkeit der Tests zu verbessern und vorhersehbare Tests zu ermöglichen. Mit dem Python‑Modulunittest.mock lässt sich das einfach umsetzen.Beispiel für Mocks
Im folgenden Code wird die langlaufende Funktiontime_consuming_function() durch einen Mock ersetzt.from unittest.mock import patch
class TestAddFunction(unittest.TestCase):
    @patch('my_module.time_consuming_function')
    def test_add_with_mock(self, mock_func):
        mock_func.return_value = 0
        result = add(2, 3)
        self.assertEqual(result, 5)time_consuming_function aufzurufen, indem ein Mock verwendet wird. Dadurch lässt sich die Testdauer verkürzen und gleichzeitig ein genaues Ergebnis erzielen.
5. Ausnahmebehandlung und benutzerdefinierte Assertions
unittest ermöglicht das Testen von Ausnahmebehandlungen. Zum Beispiel kann man überprüfen, dass in bestimmten Situationen eine Ausnahme korrekt ausgelöst wird, indem man assertRaises() verwendet.Testen von Ausnahmebehandlungen
Im folgenden Beispiel wird überprüft, dass einZeroDivisionError auftritt.def test_divide_by_zero(self):
    with self.assertRaises(ZeroDivisionError):
        divide(1, 0)divide(1, 0) ein ZeroDivisionError ausgelöst wird.Erstellen benutzerdefinierter Assertions
Für Fälle, die mit den Standard-Assertions nicht abgedeckt werden können, lässt sich eine eigene benutzerdefinierte Assertion-Methode erstellen.def assertIsPositive(self, value):
    self.assertTrue(value > 0, f'{value} is not positive')6. unittest-Test-Discovery-Funktion
Wenn Sie die Test‑Discovery‑Funktion vonunittest verwenden, können Sie automatisch alle Testdateien im Projekt finden und ausführen. Diese Funktion ist besonders bei großen Projekten nützlich.Verwendung der Test‑Discovery
Um die Test‑Discovery auszuführen, verwenden Sie den folgenden Befehl.python -m unittest discovertest_*.py-Dateien im angegebenen Verzeichnis ausgeführt. Wenn Sie Dateien oder Verzeichnisse angeben möchten, verwenden Sie die Optionen wie folgt.python -m unittest discover -s tests -p "test_*.py"7. Tipps zur Leistungsverbesserung mit unittest
Wenn die Ausführungsgeschwindigkeit von Tests langsam ist, sinkt die Entwicklungseffizienz. Hier stellen wir einige Tipps vor, um die Testperformance mitunittest zu verbessern.Datei-I/O optimieren
Tests, die das Lesen und Schreiben von Dateien erfordern, können durch Verarbeitung im Speicher beschleunigt werden. Durch die Verwendung vonStringIO können Sie ein Objekt erstellen, das sich im Speicher wie eine Datei verhält, und so Disk-I/O vermeiden.from io import StringIO
class TestFileOperations(unittest.TestCase):
    def test_write_to_memory(self):
        output = StringIO()
        output.write('Hello, World!')
        self.assertEqual(output.getvalue(), 'Hello, World!')Mocks verwenden
Um den Zugriff auf externe Ressourcen zu minimieren, können Sie Mocks verwenden, um Tests zu beschleunigen. Dadurch lassen sich Verzögerungen durch Netzwerk oder Datenbank vermeiden und die Testlaufzeit verkürzen. Im folgenden Beispiel wird ein API-Aufruf durch einen Mock ersetzt.from unittest.mock import MagicMock
class TestApiCall(unittest.TestCase):
    def test_api_response(self):
        mock_api = MagicMock(return_value={'status': 'success'})
        response = mock_api()
        self.assertEqual(response['status'], 'success')8. Zusammenfassung und nächste Schritte
In diesem Artikel haben wir von den Grundlagen des Unit-Testing mit Pythonunittest über die Verwendung von Setup und Teardown, das Testen von Abhängigkeiten mit Mocks bis hin zu Techniken zur Verbesserung der Testperformance ein breites Spektrum abgedeckt.Zusammenfassung der wichtigsten Punkte
- Grundlegende Anwendung: Erben Sie von unittest.TestCaseund nutzen Sie Assertion-Methoden, um Tests zu erstellen.
- setUp() / tearDown(): Durch das Zusammenfassen gemeinsamer Vorgänge vor und nach den Tests wird die Wiederverwendbarkeit und Lesbarkeit des Codes verbessert.
- Verwendung von Mocks: Da Funktionen ohne Abhängigkeit von externen Ressourcen getestet werden können, steigt die Testeffizienz erheblich.
- Test-Discovery: Eine nützliche Funktion, die die Testverwaltung in großen Projekten erleichtert.
- Techniken zur Leistungssteigerung: Durch In-Memory-Verarbeitung und den Einsatz von Mocks kann die Ausführungszeit der Tests verkürzt werden.
Nächste Schritte
Nachdem Sie die Grundlagen vonunittest beherrscht haben, können Sie sich an fortgeschrittenere Testmethoden wagen. Zum Beispiel können Sie „parametrisierte Tests“ einsetzen, um mehrere Eingabedaten gleichzeitig zu testen, oder mit Coverage-Tools den Testumfang des Codes prüfen, um die Teststrategie des gesamten Projekts zu stärken. Außerdem ist es sinnvoll, sich auch andere Test-Frameworks wie pytest anzusehen, um je nach Anwendungsfall weitere Optionen zu erhalten.  Tests sind ein wichtiger Bestandteil der Entwicklung. Um Bugs frühzeitig zu entdecken und die Codequalität zu erhalten, sollten Tests aktiv eingesetzt werden.
 
 


