Assertions (engl. Versicherung, Zusage) erlauben den Entwicklern für Testzwecke bestimmte Randbedingungen zu prüfen die immer erfüllt sein sollen.
Assertions geben dem Entwickler die Möglichkeit logische Bedingungen für die folgenden Fälle zu Programmieren:
- Interne Invarianten
- Invarianten im Kontrollfluß
- Vorbedingungen, Nachbedingungen, Klasseninvarianten
Durch die Implementierung dieser Invarianten kann der Entwickler die Qualität seiner Implementierung erhöhen, da Bedingungen geprüft werden können die nie verletzt sein sollen.
Der Unterschied zu Ausnahmen (Exceptions) besteht darin, dass Assertions immer gelten sollten und diese daher nicht im Normalfall kontrolliert werden müssen, da sie den Programmablauf nur unnötig verlangsamen würden. Assertions haben eine große Ähnlichkeit mit Ausnahmen sie dienen jedoch unterschiedlichen Zwecken:
Assertion | Ausnahme (Exception) | |
---|---|---|
Einsatzbereich | Nur wenn die Logik des Programm in den Augen des Entwicklers verletzt wird | Jederzeit da sie Teil der regulären Ablaufsteuerung sind |
Auswirkungen bei der normalen Programmausführung | Keine. Sie werden nicht geprüft! | Können immer Auftreten. |
Sichtbarkeit für Endanwender | Nie: Wenn das Programm nicht explizit mit entsprechenden Optionen (-ea) gestartet wurde | Nur wenn sie nicht abgefangen und behandelt werden |
Zielgruppe | Helfen dem Entwickler bei der Fehlersuche (auch beim Endanwender) |
Zusammenarbeit der Entwickler: Teil der regulären externen Spezifikation von Klassen Endanwender: Klassifikationschema für Fehlermeldungen bei Programmabbrüchen (Unbehandelte Ausnahmen) |
Theoretischer Hintergrund | Erlauben das Implementieren von Invarianten oder Vor- und Nachbedingungen von Schleifen und Routinen |
Elegantes Konstrukt zum Verlassen von Blöcken zur Behandlung von seltenen Ereignissen. Implementierter Code wird übersichtlicher da man nicht bei jeder Operation einzeln Sonderfäller prüfen muss |
Assertions bieten die folgenden Vorteile für den Entwickler:
- Der Entwickler kann Annahmen von denen er ausgeht als logische Ausdrücke implementieren und ist nicht auf Kommentare angewiesen.
- Die Konsistenzprüfungen werden im Normalfall nicht abgearbeitet und produzieren daher keinerlei Laufzeitkosten für den Anwender
- Sie geben dem Entwickler die Möglichkeit auch nach der Auslieferung seiner Anwendung zusätzliche Informationen durch Einschalten des Assertionchecking zu erhalten.
- Hintergrund: Bei C und C++ Anwendungen werden bei Kundenproblemen oft spezielle Programme mit extra Debuginformationen ausgeliefert. Dies ist bei Java nicht nötig
Notation
Einfache Variante einer Assertion:
assert Ausdruck1;
Der Ausdruck Audruck1 wird ausgewertet. Hat das Ergebnis den Wert true (wahr) so ist die Zusage wahr und das Programm weiter ausführt. Trifft die Zusage (Assertion) nicht zu wird das Programm mit einem AssertionError abgebrochen (falls es den entspechenden Optionen zum Checken der Assertions aufgerufen wurde).
Eine zweite Syntaxvariante ist:
assert Ausdruck1: Ausdruck2;
Hier fährt das Programm wie im Fall zuvor mit der Ausführung fort wenn Ausdruck1 wahr ist. Ist Ausdruck1 jedoch unwahr wird Ausdruck2 ausgewertet und der entsprechenden Instanz von AssertionError als Parameter mitgegeben und dann in der Fehlermeldung mit ausgegeben. Dieser Rückgabewert unterstützt den Entwickler bei der Analyse des aufgetretenen Fehlerfalls.
Einschalten der Prüfungen im Laufzeitsystem
Das Prüfen von Assertions kann beim Starten einer Javaanwendung mit den Optionen -ea bzw. -enableassertions eingeschaltet werden oder mit der Option -da bzw. -disableassertions ausgeschaltet werden. Die Option wird vor dem Klassennamen dessen main() Methode gestartet werden soll angegeben:
java -ea Klassenname1 java -ea paketname1... Klassenname1 java -ea paketname1.Klassename2 Klassenname1 java -da Klassenname1 java -da paketname1... Klassenname1 java -da paketname1.Klassename2 Klassenname1java
Wichtig: Die Notation mit den drei Punkten paketname1... ist teil der Aufrufsyntax. Mit ihr werden die Assertions für alle Klassen in einem Paket angeschaltet.
Anwendungsbeispiele
Überprüfen korrekter Wertebereiche
Prüfen des Personenalters bei Rentenberechnungen
assert ((personenAlter>0) && (personenAlter<150)); assert (rentenEintrittsAlter>0);
Die gleichen Assertions in der Variante mit einer Ausgabe für die Konsole
assert ((personenAlter>0) && (personenAlter<150)): personenAlter; assert (rentenEintrittsAlter>0): "negatives Renteneintrittsalter "+ rentenEintrittsAlter;
Das Kontrollieren des Werts eines Monats:
int monat; ... switch (monat) { case 1: case 2: case 3: System.out.println("Q1"); break; case 4: case 5: case 6: System.out.println("Q2"); break; case 7: case 8: case 9: System.out.println("Q3"); break; case 10: case 11: case 12: System.out.println("Q4"); break; default: assert false; }
Prüfen eines Kontrollflusses
In einen Programm soll eine der Bedingungen Ausdruck1 oder Ausdruck2 immer erfüllt sein.
void testMethode() { for (int k = 0; k<= 99; k++) { if (k == 50) return; } assert false; }
Die Assertion kann Prüfen ob ein Fehlerfall vorliegt.
Geschichtlicher Hintergrund
Assertions wurden in Java durch JSR 42 (A Simple Assertion Facility) in JDK 1.4 eingeführt. Dies führt zu einem gewissen Kompatiblitätsproblem:
- Quellcode der das Schlüsselwort assert als normalen Bezeichner in JDK 1.3 verwendete wird in JDK 1.4 nicht übersetzen da das Schlüsselwort nicht als Namen akzeptiert wird
- Quellcode der für JDK 1.4 geschrieben wurde wird nicht unter JDK 1.3 übersetzen, da javac in JDK 1.3 nicht der Syntax von assertions umgehen kann.
- Printer-friendly version
- Log in to post comments
- 6315 views