Zwei Fehler, die kein Test fand
Ein Test prüft ein Programm an einigen Eingaben, ein Beweis prüft es an allen. Das ist der Unterschied zwischen „bei mir hat es funktioniert“ und „es funktioniert immer“.
Ein Verkehrsbetrieb testet seinen Fahrkartenautomaten mit drei Fahrgästen: acht, dreißig und siebzig Jahre alt. Alle drei Tests sind grün. Trotzdem zahlen Vierzehnjährige und Fünfundsechzigjährige den falschen Preis.
Am Ende dieser Lektion
Notiz
Ich kann sagen, was ein Test zeigt und was ein Beweis zeigt.
Schlüsselwörter
| Begriff | Was er bedeutet | Beispiel |
|---|---|---|
| Test | ein Programm an ausgewählten Eingaben prüfen | alter = 8 |
| Beweis | zeigen, dass eine Aussage für alle Eingaben gilt | |
| Spezifikation | die Regel, die genau sagt, was richtig ist | |
| Gegenbeispiel | eine Eingabe, bei der eine Aussage falsch ist | |
| Erschöpfendes Testen | jede mögliche Eingabe einzeln prüfen | |
| Formale Methode | ein Verfahren, bei dem ein Rechner eine Regel für alle Fälle prüft |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Ein Test prüft nur gewählte Fälle
Ein Test ist ein Beispiel. Er zeigt: Für diese Eingabe stimmt die Ausgabe. Über alle anderen Eingaben sagt er nichts.
Die Regel, an die sich der Automat halten soll, heißt Spezifikation. Ein Test vergleicht die Ausgabe des Programms mit der Spezifikation, aber nur für die Eingaben, die jemand aufgeschrieben hat.
Wo der Automat von der Regel abweicht
| Alter | Soll in Cent | Automat in Cent | Getestet? |
|---|---|---|---|
| 8 | 150 | 150 | ja |
| 14 | 150 | 300 | nein |
| 30 | 300 | 300 | ja |
| 64 | 300 | 300 | nein |
| 65 | 200 | 300 | nein |
| 70 | 200 | 200 | ja |
Die Zellen, die Lernende ausfüllen, bleiben in dieser Vorschau leer.
Drei Tests, alle grün
def soll(alter):
# Die Regel: bis 14 Jahre 150 Cent, bis 64 Jahre 300 Cent, ab 65 Jahren 200 Cent.
if alter <= 14:
return 150
if alter <= 64:
return 300
return 200
def automat(alter):
# Der Automat vergleicht an zwei Stellen falsch.
if alter < 14:
return 150
if alter <= 65:
return 300
return 200
getestet = [8, 30, 70]
for alter in getestet:
print(alter, soll(alter) == automat(alter))
# Fuegen Sie 14 zu getestet hinzu und fuehren Sie erneut aus.
Bei wenigen Eingaben ist Testen ein Beweis
Ein Alter ist eine ganze Zahl von 0 bis 120. Das sind nur 121 Fälle. Prüft ein Programm alle 121, ist das ein Beweis, denn es gibt keinen anderen Fall mehr.
Ist der Eingabebereich klein genug, darf ein Test also alles prüfen. Das heißt erschöpfendes Testen. Der Befehl unten tut das für die zwei Schreibweisen der Altersgrenze und nennt jedes Alter, bei dem sie sich unterscheiden.
Alle 121 Alter vergleichen
python3 -c "print([a for a in range(0, 121) if (a < 14) != (a <= 14)])"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Bei großen Bereichen gibt es zu viele Fälle
Eine Zahl aus 32 Bit hat 2 hoch 32 mögliche Werte. Der erste Befehl zeigt, wie viele das sind.
Der zweite rechnet aus, wie viele Jahre ein Rechner braucht, der eine Milliarde Fälle in der Sekunde prüft. Die Eingabe besteht dabei aus zwei solchen Zahlen, das sind 2 hoch 64 Fälle. Ein Jahr hat hier 365 Tage, das Ergebnis ist abgerundet.
Wie viele Werte hat eine 32-Bit-Zahl?
python3 -c "print(2 ** 32)"Hier angezeigt, nicht ausgeführt. Erstellen Sie ein kostenloses Konto, um „Ausführen“ zu drücken und ihn im Terminal Ihres eigenen Labs einzugeben.
Jahre für 2 hoch 64 Fälle
python3 -c "print(2 ** 64 // (10 ** 9 * 3600 * 24 * 365))"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 Solver prüft alle Fälle auf einmal
Eine formale Methode nutzt Mathematik statt Ausprobieren: Ein Rechner entscheidet, ob eine Regel für alle Eingaben gilt, oder nennt ein Gegenbeispiel.
Das Werkzeug heißt Z3. Die nächste Lektion erklärt es genauer. Hier sehen Sie nur, was es kann: Gibt es eine 32-Bit-Zahl x mit Vorzeichen, die kleiner wird, wenn man 1 addiert? Z3 antwortet sat, es gibt eine, und nennt sie. #x7fffffff ist die größte solche Zahl, 2147483647, in Hexadezimalschreibweise.
Z3 fragt alle 32-Bit-Zahlen
printf '(declare-const x (_ BitVec 32))\n(assert (bvslt (bvadd x #x00000001) x))\n(check-sat)\n(get-value (x))\n' | z3 -inHier 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 denken: Je mehr Tests grün sind, desto sicherer ist das Programm für alle Eingaben. Das stimmt nicht, denn Tests zählen nur Beispiele. Ein Beweis braucht alle Fälle, oder einen Rechner, der sie gemeinsam prüft.
Weiterführend
Schreiben Sie die Regel für einen eigenen Automaten, etwa für den Preis einer Bibliotheksmahnung nach Tagen. Bauen Sie absichtlich einen Fehler an einer Grenze ein und suchen Sie ihn mit möglichst wenigen Tests.
Überlegen Sie, an welchen Stellen eines Bereichs Fehler am häufigsten stecken, und warum Grenzwerte gute Testfälle sind.