© prettyboy80/Shutterstock.com
Do Androids Dream of Electric Sheep?

Robolectric


Testen ist wichtig, darüber herrscht Einigkeit. Regelmäßiges, am besten kontinuierliches Testen führt zu höherer Qualität der Software, frühzeitiger Aufdeckung von Unstimmigkeiten in den Anforderungen und mehr Sicherheit beim Refac­toring. Unit Tests sollten mittlerweile zum Standardhandwerkszeug eines jeden Software­entwicklers gehören.

Eine der Kernanforderungen für Unit Tests ist, dass sie schnell ausgeführt werden können – je schneller, desto besser. Je weniger Zeit die Ausführungen der Unit Tests für ein Softwaremodul in Anspruch nehmen, desto mehr sind Entwickler bereit, die Tests vor und nach jeder Änderung des Codes auszuführen. Idealerweise sollte eine Testsuite in weniger als zehn Sekunden ausgeführt werden können. Grund hierfür: Die menschliche Aufmerksamkeitsspanne liegt bei etwa 8 bis 10 Sekunden [1]. Bei testgetriebenem Vorgehen sieht der übliche Entwicklungszyklus wie folgt aus: Test schreiben, Test ausführen (Rot), Code schreiben, Test ausführen (Grün), Refactoring ausführen, Test erneut ausführen (hoffentlich immer noch Grün). Während der Test ausgeführt wird, ist man zum Warten verdammt. Ist die Wartezeit zu lang, schweift man ab.

Genau diese Anforderung stellt im Android-Umfeld eine große Herausforderung dar. Unit Tests für Android-Apps müssen entweder auf dem Emulator oder einem physikalischen Gerät ausgeführt werden. Grund hierfür ist, dass die Android Runtime, die im SDK als android.jar zur Verfügung steht, nur leere Methodenrümpfe enthält. Ein Versuch, diese Methoden außerhalb des Emulators oder eines Android-Geräts aufzurufen, führt zu einer RuntimeException mit dem Hinweis darauf, dass die entsprechende Methode ausgestubbt ist. Nun könnte man versucht sein, die entsprechenden Klassen mithilfe von Mocks nachzubilden. Einerseits ist dies jedoch ziemlich aufwändig und führt andererseits dazu, dass die Mocks zu einer spiegelbildlichen Implementierung der getesteten Klasse degenerieren. Zusätzlich muss der Java-Code vor der Ausführung auf dem Emulator oder einem An­droid-Gerät noch in das DEX-Format [2] konvertiert, in ein APK gepackt und auf das Zielgerät hochgeladen werden. Alle diese Schritte führen zu einem nicht zu vernachlässigenden Overhead.

Robolectric sorgt dafür, dass Unit Tests in einer regulären JVM ausgeführt werden können (Kasten: „Projektspezifikation“). Somit entfallen alle für das Deployment auf ein Gerät notwendigen Schritte, die Turnaround-Zeiten werden kürzer, und es macht wieder Spaß, Tests auszuführen.

Installation

Um Robolectric zu nutzen, muss es in das zu testende Projekt integriert werden. Die Robolectric-Dokumentation beschreibt die Integration sowohl für Eclipse-Projekte als auch für die Verwendung von Android Studio, siehe [3]. Für diesen Artikel verwenden wir die Gradle-basierte Integration von Robolectric. Um Robolectric in ein neues Android-Projekt zu integrieren, ist wie folgt vorzugehen:

  • Projekt gemäß der Angaben im Kasten „Projektspezifikation“ anlegen

  • Robolectric-Gradle-Plug-in in das Build-Skript des Hauptprojekts integrieren (Listing 1)

  • Build-Skript für das App-Projekt konfigurieren (Listing 2)

  • Nicht vergessen: Gradle synchronisieren (Tools | Android | Sync Project with Gradle Files)

Insbesondere Schritt 3 ist essenziell: Hier werden Robolectric und Hamcrest als Abhängigkeiten für die Testphase angegeben sowie dafür gesorgt, dass beim Kompilieren doppelt vorkommende Dateien ignoriert werden.

Projektspezifikation

Create New Project

  • Application Name: RobolectricDemoJavaMagazin

  • Domain: javamagazin.de

  • (Next)

  • [x] Phone and Tablet

  • API Level: 15 (ICS)

  • (Next)

  • [x] Blank Activity

  • (Next)

  • Activity Name: MyActivity

  • Layout Name: activity_my

  • Title: MyActivity

Listing 1: (/build.gradle)

// Top-level build file where you can add configuration options common to all // sub-projects/modules. buildscript { repositories { jcenter() mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:0.12.2'  classpath 'org.robolectric:robolectric-gradle-plugin:0.12.+' } } allprojects { repositories { jcenter() } }

Listing 2: (/app/build.gradle)

apply plugin: 'com.android.application' apply plugin: 'robolectric' android {  compileSdkVersion 19 buildToolsVersion "19.1...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Gewinner-Teams

Wir bieten Lizenz-Lösungen für Teams jeder Größe: Finden Sie heraus, welche Lösung am besten zu Ihnen passt.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang