Tests, assert und Grenzfälle
Ein Test vergleicht beobachtetes Verhalten mit einer festgelegten Erwartung. Ein Unit-Test prüft eine kleine Einheit wie eine Berechnungsfunktion. Ein Integrationstest prüft das Zusammenspiel mehrerer Teile, etwa Einlesen, Rechnen und Dateischreiben.
Tests, assert und Grenzfälle#
Dateien, Fehler und Werkzeuge · Lektion 52 von 60
Voraussetzungen: Funktionen, Debugging. Lernziel: Du prüfst Verhalten reproduzierbar und unabhängig von Konsoleneingaben.
Ein Test vergleicht beobachtetes Verhalten mit einer festgelegten Erwartung. Ein Unit-Test prüft eine kleine Einheit wie eine Berechnungsfunktion. Ein Integrationstest prüft das Zusammenspiel mehrerer Teile, etwa Einlesen, Rechnen und Dateischreiben.
1#include <cassert>2 3bool istGerade(int zahl) {4 return zahl % 2 == 0;5}6 7int main() {8 assert(istGerade(0));9 assert(istGerade(2));10 assert(!istGerade(3));11 assert(istGerade(-2));12}assert aus <cassert> prüft eine Zusicherung, also eine erwartete Bedingung. Bei falscher Bedingung beendet es den laufenden Prozess mit einer Diagnose. Bei erfolgreichen Prüfungen produziert das Programm hier keine Ausgabe.
NDEBUG beachten#
Ist das Präprozessormakro NDEBUG beim Übersetzen definiert, können assert-Prüfungen vollständig entfallen. Benutze assert deshalb nicht zur Validierung von Benutzereingaben oder für notwendige Nebenwirkungen. assert(dateiSpeichern()); könnte im entsprechenden Build sogar das Speichern ganz auslassen.
Für einen dauerhaften Testlauf sollte ein Testframework Erwartungen auch im vorgesehenen Build zuverlässig ausführen. Ein Testframework stellt dafür Testregistrierung, Vergleichsfunktionen und Berichte bereit. Entscheidend ist, dass ein Fehlschlag als fehlgeschlagener Testprozess sichtbar wird.
Sinnvolle Fälle auswählen#
Prüfe normale Werte, leere Daten, kleinste und größte erlaubte Werte sowie Werte direkt daneben. Für eine Altersprüfung von 0 bis 130 sind -1, 0, 130 und 131 aufschlussreich. Ein Regressionstest hält einen behobenen Fehler fest, damit dieselbe Fehlfunktion später wieder erkannt wird.
Bei Gleitkommawerten hängt eine geeignete Toleranz von Größenordnung und Aufgabe ab. Vergleiche nicht pauschal alle Messwerte mit einer willkürlich gewählten festen Abweichung. Prüfe auch Sonderfälle wie nicht endliche Ergebnisse, wenn sie in der Anwendung möglich sind.
Tests von Ein- und Ausgabe trennen#
Eine Funktion berechnePreis(anzahl) lässt sich leichter prüfen als eine Funktion, die intern jedes Mal std::cin liest. Halte fachliche Berechnung möglichst getrennt vom Dialog. Prüfe den Dialog zusätzlich mit festgelegten Eingaben, Ausgaben und Beendigungsstatus.
Übung#
Welcher Test fehlt, wenn eine Division nur mit 8 / 2 geprüft wurde?
Lösung
Mindestens ein nichtganzzahliges Ergebnis wie 7 / 2 und die vereinbarte Behandlung eines Nullteilers. Je nach Vertrag kommen negative Zahlen, sehr große Werte und nicht endliche Eingaben dazu.
Weiterlernen#
Zurück: Debugger, Warnungen und Sanitizer · Kursübersicht · Weiter: Projekte mit CMake bauen
Kommentare 0
Kommentare sind für diese Seite deaktiviert.