Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
modul:m450:learningunits:lu04:monkeypatch [2024/10/02 10:25] – angelegt msuter | modul:m450:learningunits:lu04:monkeypatch [2024/11/12 07:30] (aktuell) – msuter | ||
---|---|---|---|
Zeile 7: | Zeile 7: | ||
Ein Unittest soll eine einzelne Funktion oder sogar nur Teile einer Funktion testen. | Ein Unittest soll eine einzelne Funktion oder sogar nur Teile einer Funktion testen. | ||
Die zu testende Funktion wird aber in der Regel Objekte verarbeiten und weitere Funktionen/ | Die zu testende Funktion wird aber in der Regel Objekte verarbeiten und weitere Funktionen/ | ||
- | Dadurch wird es schwieriger | + | Funktionen und Klassen werden bei Unittests simuliert (oder " |
- | Auch Zugriffe | + | ==== Isolation der Testobjekte ==== |
+ | Mocking hilft, sich nur auf die zu testende Funktion oder Klasse zu konzentrieren, | ||
+ | |||
+ | ==== Vermeidung externer Abhängigkeiten ==== | ||
+ | In vielen Anwendungen greifen Funktionen und Klassen auf externe Ressourcen zu, wie Datenbanken, APIs, Dateisysteme oder Netzwerke. Diese Ressourcen sind oft schwer zugänglich, | ||
+ | |||
+ | ==== Kontrolle | ||
+ | Mocks ermöglichen es, gezielt verschiedene Rückgabewerte oder Fehler zu simulieren, um zu überprüfen, | ||
+ | |||
+ | ==== Verbesserte Performance ==== | ||
+ | Da Mocks die tatsächlichen Ausführungen komplexer | ||
+ | |||
+ | Insgesamt macht Mocking Unittests flexibler, effizienter und zuverlässiger, | ||
===== Funktionen simulieren ===== | ===== Funktionen simulieren ===== | ||
- | Nehmen wir einmal an, wir möchten eine Funktion '' | + | Nehmen wir einmal an, wir möchten eine Funktion '' |
- | Diese Funktion ruft eine andere Funktion '' | + | Diese Funktion ruft eine andere Funktion '' |
- | Für unsere Unittests der Funktion '' | + | Für unsere Unittests der Funktion '' |
<code python> | <code python> | ||
- | Beispiel mit simulierter | + | # my_module.py |
+ | |||
+ | def get_data_from_database(): | ||
+ | """ | ||
+ | Diese Funktion | ||
+ | Wir simulieren diese Funktion im Test. | ||
+ | """ | ||
+ | # Hier könnte normalerweise eine Datenbankabfrage stehen | ||
+ | raise NotImplementedError(" | ||
+ | |||
+ | def process_data(): | ||
+ | """ | ||
+ | Diese Funktion ruft Daten von der Datenbank ab und verarbeitet sie. | ||
+ | """ | ||
+ | data = get_data_from_database() | ||
+ | # Verarbeiten wir die Daten (hier nur ein einfaches Beispiel) | ||
+ | return [item * 2 for item in data] | ||
</ | </ | ||
+ | |||
+ | <code python> | ||
+ | import pytest | ||
+ | from my_module import process_data | ||
+ | |||
+ | # Fixture zum Simulieren der Datenbankabfrage-Funktion | ||
+ | @pytest.fixture | ||
+ | def mock_get_data_from_database(monkeypatch): | ||
+ | """ | ||
+ | Simuliert die Funktion `get_data_from_database`, | ||
+ | """ | ||
+ | def mock_data(): | ||
+ | return [1, 2, 3] # Beispielhafte Testdaten, die anstelle echter Daten zurückgegeben werden | ||
+ | |||
+ | # Ersetzen der echten Funktion durch die simulierte Version | ||
+ | monkeypatch.setattr(" | ||
+ | |||
+ | def test_process_data(mock_get_data_from_database): | ||
+ | """ | ||
+ | Testet die Funktion `process_data`, | ||
+ | """ | ||
+ | result = process_data() | ||
+ | assert result == [2, 4, 6], "Die Daten sollten verdoppelt werden." | ||
+ | </ | ||
+ | |||
+ | Mit der Zeile '' | ||
+ | dass anstelle von '' | ||
===== Klassen simulieren ===== | ===== Klassen simulieren ===== | ||
Zeile 27: | Zeile 82: | ||
<code python> | <code python> | ||
- | Beispiel mit simulierter | + | # database_module.py |
+ | |||
+ | class DatabaseClient: | ||
+ | """ | ||
+ | | ||
+ | """ | ||
+ | def fetch_data(self): | ||
+ | # In einer echten Anwendung würde hier eine Datenbankabfrage stehen. | ||
+ | raise NotImplementedError(" | ||
+ | |||
+ | def get_processed_data(db_client): | ||
+ | """ | ||
+ | Funktion, die Daten vom DatabaseClient abruft und verarbeitet. | ||
+ | """ | ||
+ | data = db_client.fetch_data() | ||
+ | # Beispielhafte Verarbeitung: | ||
+ | return [item + 1 for item in data] | ||
</ | </ | ||
+ | <code python> | ||
+ | # test_database_module.py | ||
+ | |||
+ | import pytest | ||
+ | from database_module import get_processed_data | ||
+ | |||
+ | # Fixture zum Simulieren der Klasse DatabaseClient | ||
+ | @pytest.fixture | ||
+ | def mock_db_client(monkeypatch): | ||
+ | """ | ||
+ | Simuliert die DatabaseClient-Klasse, | ||
+ | """ | ||
+ | # Simulierte Klasse | ||
+ | class MockDatabaseClient: | ||
+ | def fetch_data(self): | ||
+ | return [10, 20, 30] # Beispielhafte Testdaten | ||
+ | |||
+ | # Ersetzen der echten DatabaseClient-Klasse durch die simulierte Version | ||
+ | monkeypatch.setattr(" | ||
+ | | ||
+ | # Instanz der simulierten Klasse zurückgeben | ||
+ | return MockDatabaseClient() | ||
+ | |||
+ | def test_get_processed_data(mock_db_client): | ||
+ | """ | ||
+ | Testet die Funktion `get_processed_data`, | ||
+ | """ | ||
+ | result = get_processed_data(mock_db_client) | ||
+ | assert result == [11, 21, 31], "Die Daten sollten um 1 erhöht werden." | ||
+ | </ | ||
+ | |||
+ | ==== Erläuterung ==== | ||
+ | ** Fixture mock_db_client: | ||
+ | |||
+ | Diese Fixture erstellt eine simulierte Version der '' | ||
+ | Mit '' | ||
+ | |||
+ | ** Test test_get_processed_data: | ||
+ | |||
+ | Der Test nutzt die Fixture '' | ||
+ | Da '' |