Unit Testing Cocoa

Vortrag am 17. März 2010

The main thing that distinguishes legacy code from non-legacy code is tests, or rather a lack of tests. Michael Feathers

Was ist ein Unit Test?

  • Testprogramm für einzelne Programmbausteine (Klassen, einzelne Methoden),
  • zustandslos, bereitet die Vorbedingungen selbst vor,
  • automatisierbar, prüft alle Nachbedingungen, Schritt im Build Prozeß,
  • normalerweise in der gleichen Sprache geschrieben wie der zu testende Code,
  • nicht Teil des ausgelieferten Programms.

Quelltext Impression

#import <SenTestingKit/SenTestingKit.h>
@interface MyClassTC : SenTestCase {}
@end
 
#import "MyClass.h"
@implementation MyClassTC
-(void)setUp {
}
 
-(void)tearDown {
}
 
-(void)testMethodXY {
  ...
  STAssertEqualObjects(@"expected", ..., @"fail");
}
@end

Was nützen mir Unit Tests?

  • Klarheit der Abhängigkeiten in meinem Code (Stichwort Dependency Injection & Inversion of Control),
  • Refactoring ohne Nervenkitzel,
  • eindeutig definiertes Verhalten (Design by Contract), Förderung der Teamarbeit,
  • keine „vergessenen“ Tests, da jeder Build alle prüft, Bedingung für Continuous Integration.

Wie geht's prinzipiell?

  • Test Framework zur bequemen Entwicklung, Ausführung und für Berichte,
  • normalerweise pro Logikbaustein (Klasse) eine Testklasse,
  • pro Bug / gewünschtem Verhalten eine Testmethode:
-(void)testRFC1123 {
  NSString *s = @"Fri, 14 Aug 2009 14:45:31 GMT";
  STAssertEqualObjects(s, [[NSDate dateFromRFC1123:s]
    rfc1123String], @"fail");
}

Wie geht's mit Cocoa

Step & Trace

dazu brauchen wir ein „Custom Executable“:

  • Pfad Developer/usr/bin/otest relativ zu „Current SDK“
  • einige Parameter und etliche Umgebungsvariablen das können wir dann als Active Executable starten und debuggen. Vorsicht:
  • Parameter und Umgebungsvariablen gehen in die *.pbxuser Datei ein und gehen drum leicht verloren.
  • die Debugsitzung startet nur, wenn alle Tests erfolgreich sind (Build Abhängigkeit) - ich kommentiere die kritischen STAsserts zeitweise aus (Holzhammer)

———

NSLog

  • Terminal: xcodebuild auf das Test Target loslassen und die NSLogs kommen auf die Konsole
  • XCode: Custom Executable als Active Executable und schon sehen wir die NSLogs auch.

Exkurs: Entwicklungsprozesse

Was ich vermisse

  • einfachere Projekteinrichtung,
  • benutzerbezogene Einstellungen abschaffen,
  • Testabdeckung messen und anzeigen. (CoverStory?) Test Coverage

Locker bleiben

Don’t stress about unit tests. They are intended as a tool for ensuring good test coverage and memory management. Use them in that way to aid your development process. ADC

  • Unit Tests verhindern natürlich nicht jeden Bug,
  • Testing-Taliban schrecken moderate Seelen oft ab,
  • ein laufendes Programm ist wichtiger als 100% Testabdeckung,
  • die ersten Tests für Spaghetti Code können allerdings frustrieren.

Querverweise / Lesetips

Vielen Dank

für Eure Aufmerksamkeit.

Feedback willkommmen an Marcus Rohrmoser

Die Folien zum Nachlesen gibt's hier:

http://mro.name/go/cocoaheads_testing

aus Sicht eines iPhone Entwicklers.

ein Vortrag bei den CocoaHeads von