Unit-Testing in Objective-C, Teil 2

Der zweite Teil unserer Serie zu Unit-Testing in Objective-C beschäftigt sich mit den Assertions. Sie beschreiben die Behauptungen bzw. Erwartungen, die innerhalb einer Testmethode an das Testobjekt gestellt werden. OCUnit stellt dafür verschiedene Makros zur Verfügung:

STAssertEquals

In Teil 1 haben wir bereits das Makro "STAssertEquals" benutzt.

Definition:
STAssertEquals(a1, a2, description, ...);
Beispiel:
STAssertEquals(4.0, exp2(2), @"2 times 2 shall be 4.");

Es vergleicht die Werte "a1" und "a2" miteinander und gibt eine Fehlermeldung inklusive des Wertes von "description" aus, wenn diese nicht gleich sind. Für "description" kann ein Formatstring (wie für "printf") definiert werden, entsprechend folgen die durch Komma getrennten Parameter.

STAssertEqualsWithAccuracy

Insbesondere bei Verwendung von Fließkommazahlen empfiehlt es sich, statt "STAssertEquals" das Makro "STAssertEqualsWithAccuracy" zu verwenden. Dieses erlaubt die Festlegung einer Abweichung, innerhalb der der erwartete Wert liegen darf.

Definition:
STAssertEqualsWithAccuracy(left, right, accuracy, description, ...);
Beispiel:
STAssertEqualsWithAccuracy(1.0, cos(0), 0.001, 
                           @"cos(0) shall be 1, but we allow a tolerance of 0.001.");

Der Parameter "accuracy" legt die maximale Differenz zwischen beiden Werten fest, im Beispiel darf der Wert von "cos(0)" also um 0.001 nach oben und unten von 1.0 abweichen.

STAssertEqualObjects

Beim Vergleich zweier Objekte ist häufig nicht die Frage, ob die Instanzen selbst identisch sind, sondern ob ihre Werte bzw. die Werte ihrer Instanzvariablen gleich sind. Ein typischer Fall ist der Vergleich zweier NSString-Objekte. OCUnit bietet dafür das Marko "STAssertEqualObjects", welches auf die "isEqual"-Methode der jeweiligen Klasse zurückgreift:

Definition:
STAssertEqualObjects(a1, a2, description, ...);
Beispiel:
NSString *string = [NSString stringWithUTF8String:"Just a test"];
STAssertEqualObjects(string, @"Just a test", @"Both strings shall be equal.");
Wer den Unterschied zu "STAssertEquals" sehen will, kann probehalber auch folgenden Aufruf probieren:
STAssertEquals(string, @"Just a test", @"Both strings shall be equal.");

Während die erste Zusicherung erfüllt wird, schlägt die zweite fehl und Xcode zeigt die Meldung "<20dd1900> should be equal to <60610300>: Both strings shall be equal." an. Wie erwartet, werden die Speicheradressen der Objekte und nicht deren Werte verglichen.

STAssertTrue und STAssertFalse

Diese beiden Makros überprüfen boolesche Ausdrücke bzw. Funktionen, die boolesche Werte zurückgeben.

Definition:
STAssertTrue(expression, description, ...);
STAssertFalse(expression, description, ...);
Beispiel:
STAssertTrue([@"Hesse" isGreaterThan:@"Goethe"], @"Hesse is greater than Goethe");
STAssertFalse([@"Hesse" isGreaterThan:@"Rilke"], @"Hesse is not greater than Rilke");

Man sollte "STAssertTrue" nicht für Vergleiche mit "==" oder "isEqual" verwenden, da hier "STAssertEquals" sowie "STAssertEqualObjects" besser geeignet sind und die verglichenen Werte in der Fehlermeldung aufführen (fügt man diese per entsprechenden Token in den Formatstring von "description" ein, kann man selbiges auch mit "STAssertTrue" erreichen, dies ist aber nicht Sinn der Sache).

STAssertNil und STAssertNotNil

"STAssertNil" vergleicht den übergebenen Wert mit "nil", "STAssertNotNil" sichert zu, dass er nicht "nil" ist. Der vorrangige Einsatzzweck sind Funktionen, die Zeiger auf Objekte zurückgeben.

Definition:
STAssertNil(a1, description, ...);
STAssertNotNil(a1, description, ...);
Beispiel:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:@"TextMate" forKey:@"editor"];
STAssertNil([dict objectForKey:@"viewer"], 
            @"Shall return nil as key is not  set in dictionary.");
STAssertNotNil([dict objectForKey:@"editor"], 
               @"Shall return not nil as key is set in dictionary.");

Im Beispiel wird ein "NSMutableDictionary" mit einem Eintrag mit dem Key "editor" erstellt, entsprechend liefert es für diesen Key ein Objekt zurück. Für andere Keys wird hingegen "nil" zurückgegeben.

STAssertThrows und STAssertNoThrow

Diese Assertions erwarten, dass eine Exception ausgelöst bzw. nicht ausgelöst wird.

Definition:
STAssertThrows(expression, description, ...);
STAssertNoThrow(expression, description, ...);
Beispiel:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:@"Xcode"];
STAssertThrows([array objectAtIndex:1], 
               @"Exception thrown as index is beyond bounds.");
STAssertNoThrow([array objectAtIndex:0], 
                @"No exception as index exists.");

Zusätzlich gibt es noch die Varianten "STAssertThrowsSpecific" und "STAssertThrowsSpecificNamed" sowie "STAssertNoThrowSpecific" und "STAssertNoThrowSpecificNamed", mit denen sich Typ und Name der Exception spezifieren lassen. Beispiel:

STAssertThrowsSpecificNamed([array objectAtIndex:1], 
                            NSException, NSRangeException, 
                            @"NSRangeException thrown as index is beyond bounds.");

Außerdem können mit "STAssertTrueNoThrow" und "STAssertFalseNoThrow" boolesche Ausdrücke ausgewertet und gleichzeitig überprüft werden, dass keine Exception erfolgt. Zwar zeigt Xcode auch ohne diese Varianten an, wenn eine Exception ausgelöst wurde, sie ermöglichen jedoch die Darstellung der Fehlermeldung direkt in der betroffenen Zeile.

STFail

Last, but not least, lässt das Makro "STFail" jeden Testfall fehlschlagen. Die Motivation dafür ist typischerweise, dass man die betroffene Methode als fehlerhaft oder unfertig markieren und dadurch deutlich machen will, dass noch Handlungsbedarf besteht.

Definition:
STFail(description, ...);
Beispiel:
STFail(@"Test not finished yet.");

Damit endet dieser Artikel. Im nächsten Teil der Serie werden wir uns mit Mock-Objekten beschäftigen.

Schlüsselwörter: objective-c, programmierung, testen, xcode

Von Thomas Dohmke vor 566 Tagen hinzugefügt


Kommentare

Kommentar hinzufügen

Twitter

Uns auf Twitter verfolgen: