Argh! Earthlings! ist, trotz fortschreitender Entwicklung, etliche Jahre alt. Dabei ist die Projekt-Struktur einfach nicht mehr zeitgemäß. Zeit für ein Refactoring zugunsten effektiverer Testbarkeit.
Heute ist Papatag. Also habe ich mir die Zeit genommen den Code von Argh! Earthlings! zu sichten und evtl. anzupassen. Um andere Ziele einfacher zu erreichen war dies schon lange nötig. Dass es aber sooo nötig war, ist mir erst hinterher bewusst geworden.
Tatbestand
Offen zugegeben hat Argh! Earthlings! keine Test-Driven-Architecture... und folgt nicht dem TTD. Es hat aber sehr wohl einen Haufen Tests, die hin und wieder mal von mir verifiziert und "grün" gemacht werden.
Das Hauptproblem aber an einer unzureichenden Code-Coverage bei Unit Tests ist aber die miese Bedienung, mit der ich mich auseinandergesetzt hatte - verglichen zu anderen Tools, die ich tagtäglich nutze, wie Eclipse.
Lange hatte ich gedacht, dass dies ein Problem von Xcode sei und habe die Tatsache hingenommen, dass ich mich für Unit Tests umständlich vorbereiten muss, um sie dann erfolgreich abzuklappern. Das machte Unit Tests nicht gerade sympathisch.
So musste ich (vermutlich wegen meiner geringen Erfahrung zu Beginn des Projekts) mit dem manuellen Wechsel zwischen den Targets für Test und Build vorlieb nehmen. Das nervte dermaßen, dass die Tests auf der Strecke blieben - schließlich war das Ziel das Spiel und nicht dessen Lebensversicherung...
Nun hat das Projekt schon ein Ausmaß angenommen, wo das Schalten von Targets nicht mehr reicht, um das Programm zu sichern oder auch nur Kleinigkeiten oder Ideen auszuprobieren.
Dabei habe ich seit einiger Zeit immer öfter den Gedanken gehabt, dass so ein Unit Test eher schnell vorbereitet und ausgeführt werden muss. Weil es geben nicht die gesamte Infrastruktur des Produkts benötigt. Das würde ja im Endeffekt auch schnelleres Feedback bei der Umsetzung der Idee mit sich bringen, was die Entwicklung beschleunigen würde. Aussicht auf Ende des Projekts und ein stabiles Release kam hoch.
Ich wollte aber auch nie die Zeit investieren, das Tool und dessen Konfiguration zu verstehen. Großer Fehler! So habe ich die Möglichkeit ein optimales Setup zu erhalten vernachlässigt - bis heute.
Hotkey Anpassung für effizientere Ausführung
Zuerst einmal habe ich mir die Hotkey-Konfiguration vorgenommen und nach einem bekannten Mapping aus Eclipse nachgebaut. Das hilft mir sofort das Programm genauso intuitiv per Tastatur zu bedienen, wie im Büro.
Programm starten mit STRG+R
Unit Test starten mit STRG+U
Suchen nach Ressourcen per STRG+SHIFT+R
Es fehlt nur noch eine Kleinigkeit: Das Springen zum namentlich korrespondierenden
Unit Tests aus der aktuellen Klasse und wieder zurück. Unter Eclipse gibt es dafür
das Plug-In MoreUnit
, das ich dort nicht mehr missen will.
Aber der Rest hilft schon mal enorm.
Aktuellere Test-Konfiguration
Damit ausgerüstet wollte ich unbedingt die Unit Tests als integralen Bestandteil des Entwicklungsprozesses sehen. Ziel soll mittelfristig der Einsatz eines permanenten Unit- und Integrationstests sein, der parallel zur IDE läuft. Sehr vielversprechend ist hierbei der OS X Server dessen Preis mich schon fast entsetzt, wenn nicht überrascht hat.
Aber bis ich den Mac zum Server mache wird es sicherlich noch eine Weile dauern. Denn vor allem sorge ich mich um die knappen Ressourcen auf meinem Mac Mini... Um aber dem Ziel einen Schritt näher zu kommen, wollte ich die Unit Tests jederzeit unkompliziert ausführen können.
Dafür habe ich mir das Projekt genauer angeschaut und die veralteten Unit Test-Konfigurationen gegen eine aktuelle, die mit Xcode 5 daherkommt, ausgetauscht.
Für iOS 7 gibt es in Xcode 5 das XCTest-Framework, das aktuell empfohlen wird.
Es ersetzt das OCUnit-Framework, was auch entsprechend als deprecated
markiert ist.
Allerdings gilt es nur für den iOS 7 Simulator, was ein Problem für Argh! Earthlings!
war. Darum habe ich mich hier für das bewährte OCUnit entschieden.
Das habe ich zunächst parallel zur alten Konfiguration angelegt:
- Projekt Root auswählen
- Unter General ein neues Target mit + anlegen.
- Im Wizard Knoten iOS und darin Cocoa Touch Unit Testing Bundle auswählen.
- Mit Next fortfahren.
- Product Name festlegen. Dabei achten, dass kein Leerzeichen vorhanden ist. Für den Namen des Targets darf, trotz Vorschlag von Xcode, kein Leerzeichen verwendet werden. Vorschläge wie "Project Tests" kann man getrost in der Pfeife rauchen, denn das Leerzeichen macht die späteren Pfade unbrauchbar und Xcode findet seine eigenen Dateien nicht mehr wieder.
- Type sinnvoll wählen: Für Produkte ab iOS 7 aktuellstes Framework "XCTest" belassen. Für Produkte darunter, etwa Argh! Earthlings! (das noch auch auf meinem iPhone 3GS und iPad 1 spielbar ist), "OCUnit (deprecated)" wählen.
- Project und Target auf das eigene Projekt legen.
- Restliche Parameter sinnvoll vergeben.
- Mit Finish abschließen.
Das Ergebnis ist ein Unterordner mit Tests des Projekts samt einem Test-Demo, das demonstrativ fehlschlägt. Das Test-Demo habe ich ungesehen weggeschmissen, denn ich habe ja bereits etliche Tests im Code verteilt. Diese habe ich nun sortiert und konzentriert auf einem Fleck, in dem Testordner, untergebracht.
Wenn ich nun STRG+U
drücke, wird das gesamte Portfolio der Unit Tests ausgeführt und
gibt die defekten Codestellen in einer einfachen Übersicht preis.
Es dauerte nun keine 30 Minuten mit zu diesem Blog Artikel, bis alle meine bisher roten, ca 4 Monate alten, roten Bugs entfernt waren.
Lessions Learned
- Tastaturbedienung macht die Arbeit effektiver.
- Aktualität sit nicht zu unterschätzen, wenn man von den Tools profitieren will. In der Regel gilt "Never Touch a Running System", aber hin und wieder muss man mal auftauchen um Luft zu holen, und die Software auf den Stand der Zeit hieven - das kostet Überwindung, Zeit und ein einfaches Versionskontroll-System euere Wahl.
- Effizienz erhält man nur, wenn man Ballast entfernt. Unnötige Programmstarts gehören dazu. Sicherlich wird das Projekt nicht frei von manuellen Test in ihrer kompletten Umgebung sein, aber zumindest entfallen Standard-Aufgaben.
Links
Ein sehr gutes Tutorial zum Thema Unit Testing inkl. Setup gibt es hier: http://www.preeminent.org/steve/iOSTutorials/XCTest/