Wie testet man einen Nachttarif am Mittag?
Ein Fake ist ein Ersatz für etwas, das ein Test nicht kontrollieren kann, zum Beispiel die Uhr oder den Zufall. Mit einem Fake läuft derselbe Test immer gleich ab.
Ein Parkhaus verlangt nachts weniger als tagsüber. Der Test läuft aber am Mittag auf dem Rechner einer Entwicklerin. Ohne Ersatz für die Uhr bleibt der Nachttarif ungetestet.
Am Ende dieser Lektion
Notiz
Ich kann Code testen, der von der Uhrzeit oder vom Zufall abhängt.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Abhängigkeit | etwas, das eine Funktion von außen braucht | die Uhr |
| Fake | ein einfacher Ersatz mit festem Verhalten | |
| Mock | ein Ersatz, der auch merkt, wie er benutzt wurde | |
| deterministisch | bei gleicher Eingabe immer mit gleichem Ergebnis | |
| Seed | der Startwert eines Zufallsgenerators | random.seed(7) |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Uhr und Zufall machen Tests unsicher
Eine Funktion, die selbst die Uhr liest, liefert jede Stunde ein anderes Ergebnis. Ein Test dafür ist mal grün, mal rot. Das nennt man einen unsicheren Test.
Dasselbe gilt für Zufallszahlen, das Netz oder eine Datenbank. Alles, was die Funktion von außen holt, ist eine Abhängigkeit.
Die Abhängigkeit als Parameter übergeben
Die einfachste Lösung: Die Funktion bekommt die Uhr als Parameter. Im Betrieb übergeben Sie die echte Uhr, im Test einen Fake.
Ein Fake ist hier eine kleine Funktion, die immer dieselbe Stunde liefert. Dann ist der Test deterministisch: Er gibt bei jedem Lauf dasselbe Ergebnis.
Zwei Fakes für zwei Tageszeiten
def gruss(uhr):
stunde = uhr()
if stunde < 12:
return "Guten Morgen"
if stunde < 18:
return "Guten Tag"
return "Guten Abend"
# Zwei Fakes: Funktionen, die immer dieselbe Stunde liefern.
def neun_uhr():
return 9
def zwanzig_uhr():
return 20
print(gruss(neun_uhr))
print(gruss(zwanzig_uhr))
# Schreiben Sie einen dritten Fake für 14 Uhr und rufen Sie gruss damit auf.
Ein Test mit fester Uhr im Lab
Im Lab legen Sie gruss.py und test_gruss.py an. Der Test enthält die zwei Fakes neun_uhr und zwanzig_uhr.
Der Testlauf zeigt am Ende OK. Das gilt um 9 Uhr genauso wie um 3 Uhr nachts.
Den Ordner anlegen
mkdir -p ~/testlaborHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Hineingehen
cd ~/testlaborHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Die Funktion schreiben
printf 'def gruss(uhr):\n stunde = uhr()\n if stunde < 12:\n return "Guten Morgen"\n if stunde < 18:\n return "Guten Tag"\n return "Guten Abend"\n' > gruss.pyHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Den Test mit den Fakes schreiben
printf 'import unittest\nfrom gruss import gruss\n\ndef neun_uhr():\n return 9\n\ndef zwanzig_uhr():\n return 20\n\nclass TestGruss(unittest.TestCase):\n def test_morgens(self):\n self.assertEqual(gruss(neun_uhr), "Guten Morgen")\n\n def test_abends(self):\n self.assertEqual(gruss(zwanzig_uhr), "Guten Abend")\n' > test_gruss.pyHier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Den Testlauf starten, letzte Zeile
python3 -m unittest test_gruss 2>&1 | tail -n 1Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Ein häufiger Fehler
Warnung
Viele glauben, ein Fake mache den Test unecht. Er ersetzt nur, was der Test nicht kontrollieren kann. Die Logik der Funktion bleibt echt. Falsch wird es erst, wenn Sie alles ersetzen: Dann testen Sie nur den Fake.
Auch Zufall lässt sich festlegen
Ein Zufallsgenerator startet mit einem Seed. Mit gleichem Seed liefert er immer dieselbe Folge. Das ist eine Art Fake, die schon in Python steckt.
Der nächste Befehl setzt zweimal denselben Seed und würfelt zweimal. Er vergleicht die beiden Würfe. Sagen Sie voraus, was herauskommt.
Zweimal mit gleichem Seed würfeln
python3 -c "import random; random.seed(7); a = random.randint(1, 6); random.seed(7); b = random.randint(1, 6); print(a == b)"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Ein Mock merkt sich, wie er benutzt wurde
Ein Mock ist ein Ersatz, der zusätzlich zählt, wie oft und womit er aufgerufen wurde. Python liefert ihn im Modul unittest.mock mit.
Mock(return_value=9) ist eine Uhr, die immer 9 liefert. Mit call_count prüfen Sie danach, ob die Funktion sie genau einmal gefragt hat.
Ein Mock als Uhr
from unittest.mock import Mock
def gruss(uhr):
stunde = uhr()
if stunde < 12:
return "Guten Morgen"
return "Guten Tag"
uhr = Mock(return_value=9)
print(gruss(uhr))
print(uhr.call_count)
# call_count zählt, wie oft die Uhr gefragt wurde.
Ein Überblick: Ersatz für verschiedene Abhängigkeiten
| Abhängigkeit | Problem im Test | Ersatz im Test |
|---|---|---|
| Uhr | Jede Stunde anderes Ergebnis | Funktion mit fester Stunde |
| Zufallszahl | Jeder Lauf anders | Festen Wert oder Seed setzen |
| Zahlungsdienst | Kostet echtes Geld | Mock, der immer Erfolg meldet |
| Datenbank | Langsam und mit Altdaten | Eine Liste im Speicher |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.