Lade Inhalt...

Continuous Integration und automatisierte Tests für Android

Masterarbeit 2013 97 Seiten

Informatik - Sonstiges

Leseprobe

Inhaltsverzeichnis

1. Einleitung
1.1. Kontext der Arbeit
1.2. Ziel der Arbeit
1.3. Aufbau der Arbeit

2. Continuous Integration als Konzept
2.1. Definition
2.2. Die zehn CI-Praktiken
2.3. Vorteile von Continuous Integration

3. Testen von Android-Anwendungen
3.1. Besonderheiten
3.1.1. Konfigurationsvielfalt
3.1.2. Ein- und Ausgabe
3.2. Testumgebungen
3.3. Test-Arten
3.4. Werkzeuge
3.4.1. Android Testing Framework
3.4.2. Monkeyrunner
3.4.3. Robotium
3.4.4. Robolectric
3.5. Beispiele
3.5.1. Beispielanwendung: PixBox-App
3.5.2. Testen mit dem ATF
3.5.3. Testen mit Monkeyrunner

4. Entwicklung einer CI-Kette für Android-Projekte
4.1. Die CI-Kette im Überblick
4.2. Jenkins CI-Server
4.2.1. Jenkins - Ein historischer Überblick
4.2.2. Die Architektur von Jenkins
4.2.3. Jenkins-Server für diese Arbeit
4.3. Versionsmanagement mit Git
4.4. Automatisierte Builds
4.4.1. Werkzeuge
4.4.2. Jenkins-Integration
4.5. Statische Codeanalyse
4.5.1. Werkzeuge
4.5.2. Jenkins-Integration
4.6. Automatisiertes Deployment
4.7. Automatisierte Tests
4.8. Automatisierte Berichte
4.8.1. Aktive Benachrichtigungen
4.8.2. Informationen auf Abruf

5. Konzept für einen skalierbaren Testpool
5.1. Benötigte Vorkenntnisse
5.1.1. Android Debug Bridge
5.1.2. Verteilte Builds mit Jenkins
5.2. Architektur-Konzept
5.3. Ablauf
5.4. Slave-Knoten
5.5. Jobs
5.5.1. Build-Job
5.5.2. Test-Job
5.6. Test-Skript

6. Fazit

A. Anhang
A.1. Abkürzungen
A.2. Unit-Test mit dem Android Testing Framework
A.3. Funktionaler Test mit dem Android Testing Framework
A.4. Blackbox-Test mit Monkeyrunner
A.5. Ant Build-File für die PixBox-App: build.xml
A.6. Testskript für Slave-Rechner
A.7. Ausgabe des Test-Skripts in der Jenkins-Konsole
A.8. Die beigelegte CD

Literaturverzeichnis

Zusammenfassung

Die vorliegende Masterthesis beschäftigt sich mit dem Einsatz von Continuous Integration in der Android-Entwicklung. Dabei liegt das Hauptaugenmerk auf automatisierten Tests. Ziel der Arbeit ist zum einen, die Besonderheiten und Möglichkeiten beim Testen von mobilen, insbesondere Android-Anwendungen aufzuzeigen. Zum anderen wird eine Ende-zu-Ende-Buildkette beschrieben, mit welcher der Integrationsprozess von Android-Anwendungen unter Einsatz des Werkzeugs Jenkins vollständig automatisiert werden kann. Zusätzlich wird ein Konzept für einen skalierbaren Gerätepool vorgestellt, mit dem es möglich ist, Android-Anwendungen parallel auf beliebig vielen Endgeräten zu testen.

Abstract

The present master thesis is concerned with the use of Continuous Integration in Android development, having a special focus on automated testing. The first ob- jective is to point out the characteristics and opportunities of testing mobile- and especially Android applications. Secondly, an end-to-end build chain is described which makes it possible to completely automate the integration process of Android applications with the aid of the tool Jenkins. Additionally, a concept for a scalable device pool is introduced which can be used to test Android applications in parallel on an unlimited number of devices.

Abbildungsverzeichnis

3.1. Android Device Fragmentation im Juli 2013

3.2. Verbreitung verschiedener Android-Versionen im Juli 2013

3.3. Test-Arten und -Frameworks

3.4. Funktionsweise des Android Testing Frameworks

3.5. PixBox-App - Registrierung und Bilder-Upload .

3.6. PixBox-App - Persönlicher PixBox-Ordner .

3.7. Testen der PixBox-App mit dem ATF

3.8. Screenshot-Vergleich mit Monkeyrunner

4.1. Die CI-Kette im Überblick

4.2. Die Weboberfläche von Jenkins

4.3. Github-Integration in Jenkins

4.4. Git-Informationen in Jenkins

4.5. Projekt in Android Studio

4.6. Ant-Aufrufe als Build-Schritt in Jenkins

4.7. Lint-Plugin - Trend

4.8. Lint-Plugin - Analyseergebnisse

4.9. Trends für Testergebnisse und Testabdeckung

5.1. Ausgabe von adb devices

5.2. Verteilte Builds mit Jenkins

5.3. Mehrere Slave-Knoten pro Rechner

5.4. Architektur - Ein Slave-Knoten pro Gerät . .

5.5. Architektur - Skalierung

5.6. Ablauf beim Testen im Gerätepool

5.7. Konfiguration eines Slave-Knotens

5.8. Slave-Knoten für verschiedene Geräte

5.9. Ordnerstruktur für Projekt und Test-Projekt

5.10. Jenkins-Arbeitsbereich für den Build-Job . .

5.11. Auswahl bestimmter Geräte im Test-Job

5.12. Auswahl von Geräte-Gruppen im Test-Job . .

5.13. Übersichtsseite des Test-Jobs

5.14. Detailseite für ein Unterprojekt

1. Einleitung

1.1. Kontext der Arbeit

Mobile Applikationen spielen eine wachsende Rolle in den Verkaufsstrategien von Unternehmen. Immer mehr Kunden nutzen mobile Geräte für Online-Shopping, so konnten im Jahr 2012 allein in den USA die Umsätze im Einzelhandel durch M- Commerce 1 um 81% auf 25 Milliarden Dollar gesteigert werden.2 Gleichzeitig steigen die Erlöse durch den Verkauf kostenpflichtiger Apps immer weiter an. Laut einer Studie von Gartner werden diese für das Jahr 2013 die Marke von 26 Milliarden Dollar erreichen.3

Bei größeren Softwareprojekten für den Desktop- und Web-Bereich erfreut sich Continuous Integration ( CI ) seit über einem Jahrzehnt immer größerer Beliebtheit. Bei dieser Entwicklungspraktik wird der gesamte Integrationsprozess für eine Software vollständig automatisiert - vom Build, über Tests, bis hin zu Dokumentation und Ausbringung. Dies führt im Regelfall zu einer erheblichen Senkung der vorhandenen Risiken und einer deutlichen Steigerung der Qualität.

Trotz der Relevanz von mobilen Applikationen verläuft deren Entwicklung oftmals weit weniger professionell und standardisiert als dies bei Desktop-Software und Webapplikationen der Fall ist. CI wird bislang nur bei wenigen Projekten eingesetzt, nicht selten wird sogar noch manuell getestet.4 Dies kann besonders bei AndroidApplikationen zu einem erheblichen Aufwand und damit verbundenen Kosten führen, da die Menge an unterschiedlichen Geräten, Konfigurationen, OS-Versionen und damit der zu testenden Kombinationen sehr groß ist.

Automatisierte Tests für Android-Applikationen bringen - bedingt durch Archi- tektur und Bedienung der Geräte - besondere Erfordernisse mit sich. Mittlerweile existieren einige Test-Werkzeuge und -Frameworks, welche versuchen, diesen Er- fordernissen gerecht zu werden. Auch für das automatisierte Bauen und Ausbringen von Applikationen auf Geräte sowie das dortige Ausführen von automatisierten Tests stehen diverse Werkzeuge zur Verfügung. All diese Werkzeuge lassen sich in einen CI-Prozess integrieren, jedoch ist dies Stand November 2013 eher unzusammenhän- gend und oft spärlich dokumentiert, da die Android-Entwicklung selbst noch relativ jung ist. Dementsprechend selten wird CI bislang in der Android-Entwicklung ein- gesetzt.

1.2. Ziel der Arbeit

Ziel dieser Arbeit ist es, unter Verwendung des CI-Systems Jenkins eine Ende-zu- Ende-Kette für die Android-Entwicklung zu beschreiben, mit der sich der Build- Prozess einer Anwendung vollständig automatisieren lässt: nach der Integration neu- er Software-Features wird ein Projekt automatisch aus einem Versionskontrollsystem bezogen, analysiert, gebaut und getestet. Anschließend werden Analyse- und Tester- gebnisse durch das CI-System visualisiert und ein ausführbares Programm ausgelie- fert. Für jeden dieser Schritte existieren verschiedene Werkzeuge, welche im Rahmen der Arbeit auf ihr Zusammenspiel mit Android und Jenkins untersucht wurden.

Besonderes Gewicht liegt bei dieser Arbeit auf dem automatisierten Testen von Android-Anwendungen. Neben der Evaluierung von Besonderheiten auf diesem Ge- biet wurden einige wichtige Test-Frameworks untersucht, welche für Android zur Verfügung stehen. Dabei wurde eine Beispielanwendung nebst einiger typischer Test- fälle entwickelt, um die praktische Arbeit mit diesen Frameworks zu veranschauli- chen.

Schließlich wurde ein Konzept für einen Testpool ausgearbeitet, welcher im Rahmen des CI-Systems genutzt werden kann. Mit diesem ist es möglich, Anwendungen par- allel auf verschiedene Android-Geräte oder -Emulatoren auszubringen und diese dort zu testen. In den Pool lassen sich beliebig viele Geräte integrieren, er ist also frei skalierbar. Des Weiteren bietet er die Möglichkeit, flexibel zu wählen, auf welchen Geräten getestet werden soll.

1.3. Aufbau der Arbeit

Kapitel 2 schafft die Grundlage für diese Arbeit und fasst das Konzept von Con- tinuous Integration zusammen. Kapitel 3 beschäftigt sich mit den Besonderheiten beim Testen von Android-Anwendungen, stellt die wichtigsten Test-Frameworks vor und erläutert deren Funktionsweise. Zudem werden die angesprochenen Praxisbei- spiele gezeigt. Kapitel 4 beschreibt ausführlich die entwickelte CI-Kette und ihre einzelnen Komponenten, während Kapitel 5 das Konzept für den angesprochenen Testpool vorstellt. Abgeschlossen wird die Arbeit mit einem Fazit in Kapitel 6.

2. Continuous Integration als Konzept

2.1. Definition

Der Begriff Continuous Integration wurde erstmalig von Kent Beck im Zusammenhang mit Extreme Programming verwendet. Geprägt wurde er jedoch vor allem durch Martin Fowler, der die kontinuierliche Integration in seinem gleichnamigen Fachartikel5 ausführlich als Softwareentwicklungspraktik beschreibt. Zusammenfassend erklärt Fowler CI folgendermaßen (aus dem Englischen übersetzt):

Continuous Integration ist eine Softwareentwicklungspraktik, bei der Team mitglieder ihre Arbeit häufig integrieren. Üblicherweise integriert jedes Teammitglied mindestens einmal täglich, was zu vielfachen Integrationen pro Tag f Ührt. Jede Integration wird durch einen automatisierten Build und automatisierte Tests gegengepr Üft, um Fehler so schnell wie möglich aufzudecken. Dieser Ansatz f Ührt in den Augen vieler Teams zu einer erheblichen Reduzierung von Integrationsproblemen und erlaubt es, komplexe Software schneller zu entwickeln.

Fowler beschreibt in seinem Artikel zehn Praktiken, welche zusammengesetzt zu kontinuierlicher Integration führen. In [DMG07] und [Wie11] werden diese Praktiken aufgegriffen und ergänzt.

Abschnitt 2.2 gibt (auf Basis dieser drei Quellen) einen Überblick über die zehn CI-Praktiken, während Abschnitt 2.3 einige Vorteile erläutert, die der Einsatz von CI mit sich bringen kann.

2.2. Die zehn CI-Praktiken

Gemeinsame Codebasis

In Software-Projekten sammelt sich mit der Zeit eine große Menge von Dateien und Daten an. Diese werden üblicherweise in einem Versionskontrollsystem (VCS) wie Subversion, Git oder Perforce gehalten und verwaltet. Das VCS sollte sich an einem Platz befinden, der allen Entwicklern und Projektbeteiligten bekannt und diesen zugänglich ist, sodass zu jeder Zeit die neueste Version des Source-Codes bezogen werden kann. Des Weiteren ist es wichtig, nicht nur Quellcode im VCS abzulegen sondern alle Komponenten, die benötigt werden, um einen funktionierenden Build zu erstellen. Dies können beispielsweise Konfigurationsdateien, Test- und Installations- Skripte, Datenbankschemata oder zusätzlich benötigte Bibliotheken sein. Als Faust- regel schlägt Fowler vor, im VCS alle Komponenten zu halten, die man benötigt, um das System auf einem frisch aufgesetzten Rechner zum Laufen zu bringen.

Automatisierter Build

Die Erstellung eines funktionierenden Builds kann ein aufwändiger Prozess sein, da dieser oftmals nicht nur das Kompilieren des Quellcodes enthält, sondern viele weitere Schritte beinhalten kann, wie z.B. das Bewegen von Dateien, das Laden von Datenbankschemata, Aspekte der Qualitätssicherung (insbes. Tests) oder die Verteilung und/oder Installation des Softwareprodukts. All diese Schritte manuell auszuführen, kann sehr zeitaufwändig und fehleranfällig sein, besonders wenn häufig integriert wird. Daher ist es beim Einsatz von CI erforderlich, den Build-Prozess vollständig zu automatisieren.

Werkzeuge zum Automatisieren von Builds existieren schon lange. Angefangen bei make aus der Unix-Welt über Ant und Maven aus dem Java-Umfeld bis hin zu Skript- sprachen wie Ruby, Python oder Groovy gibt es eine Vielzahl an Möglichkeiten, um eine vollständige Automatisierung des Build-Prozesses zu erreichen. Diese können kombiniert werden, die Anzahl der verwendeten Technologien sollte aus Performan- cegründen aber so gering wie möglich gehalten werden. Um überflüssige Buildzeit einzusparen, sollte eine Analyse stattfinden, welche Komponenten verändert wurden, damit tatsächlich nur diese neu gebaut werden. Hierbei müssen allerdings Abhängig- keiten zu anderen Komponenten beachtet werden, die dann ggf. auch einen Rebuild erfordern.

In [Wie11] wird darauf hingewiesen, dass ein automatisierter Build-Prozess angemes- sene Fortschrittsmeldungen ausgeben sollte.Alle logischen Schritte wie Kompilieren, Testen, Inspizieren, Packen, Verteilen usw. sollten im Build-Protokoll nachvollzieh- bar sein. Auch sollte der Build-Prozess in kurzen regelmäßigen Abständen Rückmel- dungen geben, dass er noch läuft, um feststeckende Builds schneller identifizieren zu können.6

Selbsttestender Build

Ein vollständig automatisierter Build sollte nicht nur ein ausführbares Programm erzeugen, sondern dieses auch selbst begutachten. Man spricht von einem selbst- testenden Build, wenn automatisierte Tests Bestandteil des Build-Prozesses sind. Meldet mindestens einer dieser Tests Fehler, sollte auch der Build selbst fehlschla- gen. Ein CI-System sollte in der Lage sein, solche selbsttestenden Builds zu erstellen.

In [Wie11] wird erläutert, dass ein komplett selbsttestender Build auf allen Ebenen prüft, angefangen beim Kompilieren, über Unit-Tests, Komponententests und Systemtests, bis hin zu Inspektionen, wie etwa der statischen Codeanalyse oder dem Messen der Testabdeckung.7

Tägliche Integration

Eine wichtige Regel für CI ist, dass jeder Entwickler mindestens einmal täglich seine Änderungen integrieren sollte. Dies bedeutet konkret, dass ein Entwickler seine lokale Arbeitskopie der Anwendung (oder Teilen der Anwendung) auf den aktuellen Stand der gemeinsamen Codebasis bringt, seine Änderungen integriert und einen lokalen Build (inklusive Tests) durchführt. Nur wenn der Build erfolgreich war, darf der Entwickler seine Änderungen ins VCS einchecken. Auf diese Weise können auftretende Konflikte schnell aufgedeckt und gelöst werden, da jede Änderung und somit die Anzahl der potenziellen Fehlerquellen sehr klein ist.

Durch die Praxis der häufigen Integration sind Entwickler dazu angehalten, ihre Arbeit in sehr kleine Pakete zu unterteilen. Dies kann anfänglich dazu führen, dass Entwickler das Gefühl haben, nichts Bedeutungsvolles zu leisten. Oft wird die Mo- tivation mit der Zeit aber sogar gesteigert, da täglich kleine Erfolgserlebnisse zu verzeichnen sind.8

Builds und Tests nach jeder Änderung

Anstatt manuell Builds nach einer oder mehreren Änderungen oder Nightly-Builds durchzuführen, sollte ein CI-Server zum Einsatz kommen, der mit dem VCS gekop- pelt ist und nach jeder Änderung automatisch einen Build durchführt. Auf diese Weise können Entwickler unmittelbar nach dem Build über dessen Erfolg oder Miss- erfolg benachrichtigt werden und eventuell auftretende Konflikte zeitnah lösen.

Wenn häufig und von vielen Entwicklern integriert wird und die Build-Zeit hoch ist, kann es zu einem großen Rückstau an Builds kommen. Für diesen Fall empfiehlt [Wie11], eine Kombination aus einem schnellen Build mit geringem Testumfang und einem langsameren Build mit vollem Testumfang und dafür reduzierter Frequenz einzusetzen.9

Schnelle Buildzeiten

Wie aus dem vorherigen Abschnitt hervorgeht, ist die schnelle Rückmeldung ein wesentlicher Aspekt von CI. Lange Buildzeiten können dem Konzept der schnellen Rückmeldung ganz erheblich entgegenwirken und sollten deshalb soweit wie möglich vermieden werden.

In [Fow06] wird darauf hingewiesen, dass der häufigste Grund für lange Buildzeiten das automatisierte Testen ist. Besonders Tests, welche auf externe Dienste wie z.B. Datenbanken zugreifen, können viel Zeit in Anspruch nehmen. Fowler empfiehlt hier, den Build in mehrere, hintereinander gelagerte Stufen zu zerlegen (Build-Pipelining). Die erste Stufe könnte z.B. die Kompilierung des Codes und das Ausführen von ein- fachen Unit-Tests enthalten, die schnell ausgeführt werden können. Erst in einer zweiten Stufe werden dann komplexere Tests ausgeführt, welche mehr Zeit bean- spruchen. Mit Build-Pipelining ist es einerseits möglich, schnellere Builds durchzu- führen, die nicht alle Stufen enthalten, auf der anderen Seite können spätere Stufen entfallen, falls ein Build schon in einer frühen Stufe fehlschlägt.

[Wie11] empfiehlt neben dem Build-Pipelining auch die Modularisierung von Builds. Dabei wird ein System in mehrere Module zerlegt, die unabhängig voneinander ge- baut werden können. So müssen nur diejenigen Module neu gebaut werden, in denen tatsächlich Änderungen stattgefunden haben. Ein modularisierter Build kann zudem verteilt werden. Dabei findet das Bauen mehrerer Module gleichzeitig auf verschie- denen Rechnern statt.10

Testen in gespiegelter Produktionsumgebung

Für authentische Tests ist es wichtig, über eine Testumgebung zu verfügen, die der späteren Produktionsumgebung so ähnlich wie möglich, im Optimalfall ein Spiegel derer ist. In vielen Projekten gestaltet sich dies schwierig. Mögliche Gründe dafür können z.B. zu hohe Kosten, Nichtverfügbarkeit aller benötigten Daten, oder die Vielfältigkeit möglicher Produktionsumgebungen (insbes. bei Desktopsoftware) sein. Trotzdem sollte die Produktionsumgebung so detailliert wie möglich nachgebildet werden. Hilfreich kann hier der Einsatz von Rechnervirtualisierung und/oder Cloud- Computing sein.11

Einfacher Zugriff auf Build-Ergebnisse

In einem Softwareprojekt ist es für viele Beteiligte immer wieder nötig, Zugriff auf die neueste Version des zu erstellenden Produkts (als ausführbare Datei) zu haben, sei es zu Testzwecken, für Demonstrationen, oder um im Livebetrieb zu sehen, was sich seit der letzten Version verändert hat. Anstatt solche Buildergebnisse auf einem FTP-Server oder einem Netzlaufwerk zu halten, wird in einem CI-System jedes Ar- tefakt im Kontext seines Builds aufbewahrt. So stehen für jeden Build nicht nur eine ausführbare Datei, sondern auch diverse nützliche Informationen zur Verfügung, z.B. wer den Build wann erstellt hat und welche Änderungen in diesen Stand eingeflossen sind.12

Automatisierte Berichte

Nach Fowler ist vollständige und prägnante Kommunikation eine der tragenden Säulen von CI. Ein gutes CI-System trägt die richtige Information auf geeignete Art und Weise zum richtigen Zeitpunkt an die richtige Stelle - und das automatisch. In [DMG07] wird dies als kontinuierliche R Ückmeldung bezeichnet.

[Wie11] unterteilt die Informationen, die ein CI-System bereitstellen sollte, in die folgenden drei Bereiche:13

- Aktive Benachrichtigungen

Treten beim Build Probleme auf, werden zeitnah diejenigen Personen benach- richtigt, die zur Problemlösung beitragen können. Die Übermittlung geschieht über gängige Kanäle (meist per E-Mail, in einigen Fällen aber auch z.B. per

Instant Messenger oder SMS). Die Nachricht sollte präzise Informationen über das Problem enthalten und dieses möglichst weit eingrenzen.

- Öffentliche Statusanzeige

An einem häufig besuchten Platz befindet sich ein Indikator, der in vereinfach- ter Form den Status des CI-Systems (etwa des letzten Builds) anzeigt. Dies kann ein Monitor, aber auch z.B. eine ampelartige Darstellung mit Lampen sein.

- Detaillierte Informationen auf Abruf

Das CI-System bietet eine Plattform (i.d.R. eine Webseite), auf der detail- lierte Informationen zu allen Builds und aufgetretenen Problemen archiviert werden und eingesehen werden können. Diese Informationen können z.B. die Auswertungen einzelner Builds, oder wichtige Kennzahlen über den Verlauf eines Projekts sein.

Automatisiertes Deployment

Im Normalfall existieren mehrere Umgebungen, auf die ein Softwareprodukt in re- gelmäßigen Abständen ausgebracht werden muss. Dies sind üblicherweise ein oder mehrere Testumgebungen sowie die Produktionsumgebung. Bei der Nutzung von CI kann und sollte auch dieser Schritt automatisiert werden. Dabei spielt nicht nur die Ausbringung selbst eine Rolle, sondern auch eine genaue Protokollierung aller Vorgänge. So sollte z.B. festgehalten werden, wer wann welche Version auf welche Umgebung ausgebracht hat.

2.3. Vorteile von Continuous Integration

Nachdem im vorangegangenen Abschnitt die Praktiken erläutert wurden, die zu erfolgreicher CI führen, sollen nun hier in Kurzform einige Vorteile dargestellt werden, welche der Einsatz von CI mit sich bringen kann.14

Reduzierte Risiken

Bei Projekten ohne CI, in denen in großen Abständen integriert wird, kann es sehr schwierig sein, den aktuellen Projektfortschritt zu bestimmen und abzuschätzen, wie lange es brauchen wird, um das Projekt abzuschließen. Die Integration am Ende einer längeren Phase ist oft ein sehr arbeitsintensives und aufreibendes Ereignis für alle Beteiligten. Durch den Einsatz von CI weiß man an jedem Punkt des Projekts genau darüber Bescheid, was schon funktioniert, was noch nicht und welche Fehler noch zu beheben sind. Durch die Häufigkeit wird jede Integration zu einem Nicht-Ereignis.

Verbesserte Produktqualität

Die Qualität eines Softwareprodukts wird enorm gesteigert, da früher, öfter, gründ- licher und umfangreicher getestet wird, als dies bei einer manuellen Vorgehensweise möglich wäre.

Allzeit auslieferbare Produkte

Es steht zu jeder Zeit eine ausführbare Version des Produkts zur Verfügung, welche für Tests und Demonstrationen verwendet werden kann. Dadurch werden Projekte transparenter.

Dokumentierter Build-Prozess

Durch die vollständige Automatisierung des Build-Prozesses wird dieser auch durchgehend dokumentiert.

Höhere Motivation

Durch häufige Integration entsteht häufige Rückmeldung. Viele positive Rückmel- dungen führen bei Entwicklern zu höherer Motivation. Des Weiteren resultieren die kurzen Arbeitsschritte zwischen den Integrationen oft in einem nachhaltigen Arbeit- stempo.

Verbesserter Informationsfluss

Es liegen zu jeder Zeit automatisch generierte Informationen zum Stand eines Projekts vor. Werden diese vom CI-System entsprechend aufbereitet und visualisiert, können sie die Entscheidungsfindung innerhalb des Projekts unterstützen.

3. Testen von Android-Anwendungen

Dieses Kapitel beschäftigt sich mit dem automatisierten Testen von Android-Anwendungen. Dabei werden zunächst Besonderheiten aufgezeigt, welche auf diesem Gebiet zu be- achten sind. Anschließend werden einige der bekanntesten Werkzeuge zur Durch- führung automatisierter Tests vorgestellt. Abgeschlossen wird das Kapitel durch die Beschreibung einer Beispielanwendung sowie einigen beispielhaften Tests, welche für diese entwickelt wurden.

3.1. Besonderheiten

3.1.1. Konfigurationsvielfalt

Die größte Herausforderung beim Testen von Android-Anwendungen ist die Konfigu- rationsvielfalt. Die Menge der zur Verfügung stehenden Android-Geräte ist immens groß, fast unüberschaubar. Die Entwickler der beliebten Android-App OpenSignal führen seit 2012 eine Studie durch, bei der für jeden Download der App Informa- tionen über das herunterladende Gerät sowie das darauf installierte Betriebssystem gesammelt werden. Bei insgesamt 682.000 Downloads lag die Anzahl der unterschied- lichen verwendeten Geräte im Jahr 2012 bei knapp 4000 und im Juli 2013 bereits bei annähernd 12000. Der Trend zur sog. Device Fragmentation scheint sich also weiterhin stark fortzusetzen. Abbildung 3.1 zeigt eine von OpenSignal erstellte Vi- sualisierung unterschiedlicher Android-Geräte, mit denen die App in den letzten Monaten heruntergeladen wurde.15

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 3.1.: Android Device Fragmentation im Juli 2013

Während die Verfügbarkeit so vieler verschiedener Geräte für den Endbenutzer eher vorteilhaft ist (in jeder Preisklasse ist ein entsprechendes Android-Gerät zu finden), stellt sie eine große Herausforderung an das Testen von Applikationen dar. Es exis- tieren Geräte unterschiedlichster Größen, welche verschiedene Bildschirmauflösun- gen nutzen. Hinzu kommt die große Anzahl verschiedener Android-Versionen. Jedes Jahr erscheint mindestens eine neue Version des Betriebssystems, wobei viele ältere Geräte nicht in der Lage sind, diese auszuführen. Dies führt dazu, dass zur selben Zeit viele verschiedene Android-Versionen im Umlauf sind. Abbildung 3.2 zeigt die ebenfalls im Juli 2013 von OpenSignal gemessene Verbreitung der unterschiedlichen Versionen des Android-OS.

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 3.2.: Verbreitung verschiedener Android-Versionen im Juli 2013

Wollte man sicherstellen, dass eine Anwendung auf allen verfügbaren Geräten und OS-Versionen korrekt läuft, müsste man eine unmöglich zu bewältigende Anzahl an Kombinationen aus Geräten und Betriebssystemen testen. Natürlich ist nicht jedes Gerät komplett unterschiedlich und eine Anwendung muss nicht zwingend für die Ausführung auf allen OS-Versionen konzipiert sein. Jedoch ergibt sich, selbst wenn man nur einen ausgewählten Teil der verfügbaren Kombinationen abdecken möchte, schnell eine sehr komplexe Konfigurationsmatrix.

Ausgehend von diesen Fakten ist es nur schwer vorstellbar, dass selbst größere kommerzielle Entwicklungen für Android immer noch ohne automatisierte Tests auskommen. Bei komplexeren Anwendungen kann - wenn manuell getestet wird - selbst das Abdecken von nur wenigen Konfigurationen sehr viel Zeit in Anspruch nehmen und somit hohe Kosten verursachen.

3.1.2. Ein- und Ausgabe

Mobile Endgeräte nutzen spezielle Technologien für Benutzereingaben und die Ein- und Ausgabe von Daten. Eine wichtige Aufgabe von Testwerkzeugen für die mobile Entwicklung besteht darin, auf diese Technologien zuzugreifen, sie zu nutzen oder zu simulieren.

Benutzereingaben

Moderne Smartphones verfügen im Normalfall über keine Hardware-Tastatur, die Benutzereingabe erfolgt hauptsächlich über den Touchscreen. Neben dem normalen Tippen auf den Bildschirm können Gesten wie z.B. Wischen erkannt werden. Zudem verfügen die Geräte meist über Hardwaretasten, etwa die Menütaste oder die Lautstärkeregler. Beim Testen von Anwendungen müssen all diese Formen der Eingabe ausgeführt werden können, um Benutzereingaben zu simulieren.

Interne Hardware

Die meisten mobilen Geräte verfügen über eingebaute Hardware-Features, welche in Anwendungen genutzt werden können. Beispiele sind die Kamera und der GPS- Sensor. Diese Features können auf verschiedenen Geräten sehr unterschiedlich imple- mentiert sein, was sowohl bei der Entwicklung als auch beim Testen von Anwendun- gen berücksichtigt werden muss. Die Aufgabe von Testwerkzeugen kann entweder darin bestehen, die geräteinterne Hardware zu bedienen oder zu simulieren.

Ausgabe

Displaygröße und -auflösung sowie die Orientierung eines mobilen Geräts haben einen großen Einfluss auf das optische Erscheinungsbild einer Anwendung. So kann eine App - je nach zur Verfügung stehendem Platz und ob das Gerät hochkant oder quer gehalten wird - sehr unterschiedlich aussehen. Häufig werden bei der Entwick- lung von Apps mehrere Layouts angelegt, damit das Erscheinungsbild unabhängig von den genannten Kriterien stimmig ist. Layout-Tests sind daher eine wichtige und oft durchgeführte Aufgabe.

Eine weitere Besonderheit bei mobilen Anwendungen ist die Mehrsprachigkeit, da Apps über den Play Store international heruntergeladen werden können. Für eine Anwendung können mehrere Lokalisierungen angelegt werden, so dass die Text- ausgabe in der Sprache des jeweils installierten Betriebssystems erfolgen kann. Die Überprüfung der korrekten Lokalisierung ist ein typischer Testfall für eine Android- Anwendungen.

3.2. Testumgebungen

Für automatisierte Tests von Android-Anwendungen stehen grundsätzlich zwei mög- liche Umgebungen zur Verfügung: ein echtes (physisches) Gerät oder ein Emulator.

Das Android-SDK16 stellt einen Emulator bereit. Dieser läuft auf einem Computer und ist in der Lage, die meisten Hardware- und Softwaremerkmale eines typischen Android-Geräts nachzustellen. Entwickelte Anwendungen können auf dem Emulator installiert und ausgeführt werden, Benutzereingaben lassen sich manuell mit Maus und Tastatur tätigen. Mit dem Werkzeug Android Virtual Devices (AVD) können beliebig viele virtuelle Geräte erstellt werden, welche sich im Emulator starten las- sen. Dabei ist es möglich, Hardware-Merkmale, wie etwa Displaygröße, Prozessor oder Hauptspeicher zu konfigurieren. Des Weiteren kann jede beliebige Version des Android-OS auf dem virtuellen Gerät installiert werden. So ist es möglich, spezifi- sche, real existierende Geräte weitgehend authentisch zu simulieren.17

Im Kontext des automatisierten Testens hat der Einsatz von Emulatoren den offensichtlichen Vorteil, dass nicht zwingend viele echte Geräte angeschafft werden müssen, um Tests durchführen zu können. Allerdings bringt er auch einige Nachteile und Einschränkungen mit sich:

- Es können keine Anrufe getätigt oder SMS versendet werden.
- Kamera und GPS-Sensor können simuliert werden, geben aber nicht zwingend Auskunft darüber, wie sich die Hardware auf einem echten Gerät verhalten würde. Die Verwendung von Bluetooth ist mit dem Emulator nicht möglich.
- Der Emulator ist sehr langsam. Selbst auf modernen Rechnern läuft die Be- dienung nicht flüssig. Viele Aktionen dauern so deutlich länger als auf einem echten Gerät. Des Weiteren dauert der Start einer Emulator-Instanz relativ lang. Je nach Konfiguration des Emulators und der zur Verfügung stehenden Rechenleistung kann ein Start mehrere Minuten benötigen.
- Es lassen sich zwar parallel mehrere Instanzen des Emulators starten, je nach zugewiesenem Speicher kann dies jedoch selbst moderne Rechner schnell in die Knie zwingen.

Für viele Tests kann der Einsatz von Emulatoren völlig ausreichend sein. Werden jedoch gerätespezifische Eigenschaften benötigt, muss auf echten Geräten getestet werden. Aufgrund des hohen Resourcenverbrauchs des Emulators skaliert dieser nur schlecht: parallele Tests auf vielen verschiedenen Emulatoren sind nur unter Verwendung mehrerer Rechner möglich (mehr dazu in Kapitel 5).

3.3. Test-Arten

Im folgenden Abschnitt werden eine Reihe von Werkzeugen und Frameworks vorgestellt, mit denen automatisierte Tests für Android-Applikationen durchgeführt werden können. Um Missverständnissen vorzubeugen, sollen an dieser Stelle einige Begrifflichkeiten geklärt werden.

Generell lassen sich beim Testen von Android-Anwendungen zwei verschiedene Arten von Tests unterscheiden: Unit-Tests und funktionale Tests.

Unit-Tests werden aus der Perspektive des Programmierers geschrieben. Sie stellen sicher, dass eine (möglichst kleine) Einheit einer Anwendung - etwa eine Methode einer Klasse - eine Reihe definierter Aufgaben korrekt ausführt. Dabei wird geprüft, ob die Methode beim Verarbeiten von definierten Eingaben die erwarteten Ausgaben liefert. Funktionale Tests hingegen werden aus der Sicht des Benutzers geschrieben und decken echte Anwendungsfälle ab. Sie stellen sicher, dass sich das System in einem konkreten Anwendungsfall so verhält, wie es vom Benutzer erwartet wird.18

Funktionale Tests lassen sich weiter klassifizieren in Whitebox - und Blackbox-Tests. Bei ersteren ist der Quellcode der AUT19 bekannt und es wird anhand des Codes geprüft. Bei letzteren hingegen sind keine Kenntnisse über die innere Funktionsweise der Anwendung vorhanden und es wird nur anhand von Anforderungen getestet.

Instrumentation ist eine Vorgehensweise, bei welcher der Lebenszyklus und das Verhalten von Komponenten einer Android-Anwendungen von außen gesteuert werden kann. Der Begriff wird im folgenden Abschnitt genauer erläutert.

Schlussendlich ist es noch wichtig zu wissen, in welcher Laufzeitumgebung ein Test läuft. Einfache Java-Klassen können direkt in der regulären JVM20 getestet werden. Wird jedoch Zugriff auf die Android-API benötigt, muss der Test in der Android- spezifischen Dalvik-VM laufen. Dazu ist es nötig, diesen auf einem Gerät oder Emu- lator auszuführen.

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 3.3 veranschaulicht den hier dargestellten Sachverhalt und zeigt, welche Test-Arten von den in dieser Arbeit vorgestellten Werkzeugen unterstützt werden.

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 3.3.: Test-Arten und -Frameworks

3.4. Werkzeuge

3.4.1. Android Testing Framework

Das Android Testing Framework (ATF) ist ein fester Bestandteil des Android SDK und stellt sowohl eine Architektur als auch diverse Werkzeuge zur Verfügung, um Android-Applikationen automatisiert zu testen. Unit-Tests sind dabei ebenso möglich wie funktionale Tests.

Abbildung 3.421 und die folgenden Abschnitte sollen einen groben Überblick über die Funktionsweise und die Möglichkeiten des Frameworks geben. Eine detaillierte Dokumentation findet sich unter [And13f] und den dort verlinkten Seiten.

Teststruktur

Das ATF basiert auf JUnit und setzt eine standardisierte Struktur von Testprojekten voraus: ein JUnit-Test besteht aus einer oder mehreren Methoden, die isoliert einen bestimmten Teil der AUT testen. Diese Methoden werden in Testklassen gehalten, welche wiederum zu Test-Suites zusammengefasst werden können.

Abbildung in dieser Leseprobe nicht enthalten

Abbildung 3.4.: Funktionsweise des Android Testing Frameworks

Alle Testklassen, bzw. Test-Suites werden in einem Paket (Test package) zusammengefasst. Dieses Testpaket kann nun gebaut und zusammen mit der zu testenden Anwendung (Application Package) geladen werden. Um die Tests auszuführen, verwendet JUnit einen sog. Test-Runner. Das ATF bringt mit dem InstrumentationTe stRunner einen spezialisierten Test-Runner mit, welcher in der Lage ist, Androidspezifische Testklassen auszuführen

Testprojekte

Tests sind, wie Android-Anwendungen selbst, in Projekten organisiert. Das AndroidSDK hält Werkzeuge bereit, um solche Testprojekte zu erstellen und zu aktualisieren. Dies kann über die Android Developer Tools direkt aus der Entwicklungsumgebung heraus oder manuell über die Kommandozeile geschehen. Die Werkzeuge erstellen automatisch die benötigte Ordnerstruktur und konfigurieren die Manifest-Datei für das Testprojekt. Des Weiteren können auch Build-Dateien für Ant generiert werden, mit deren Hilfe das Testprojekt gebaut werden kann.

[...]


1 Mobile Commerce: elektronischer Handel unter Verwendung mobiler Endgeräte

2 Vgl. [eMa13]

3 Vgl. [Gar13]

4 Vgl. [Taf13]

5 s. [Fow06]

6 Vgl. [Wie11], S. 33

7 Vgl. [Wie11], S. 35

8 Vgl. [Fow06]

9 Vgl. [Wie11], S. 38

10 Vgl. [Wie11], S. 38

11 Vgl. [Wie11], S. 39

12 Vgl. [Wie11], S. 40

13 [Wie11], S. 41

14 Vgl. [Wie11], S. 23-30

15 Vgl. [Ope13]

16 http://developer.android.com/sdk/index.html

17 Vgl. [And13g]

18 Vgl. [Can13]

19 Application Under Test; z. Dt.: die zu testende Anwendung

20 Java Virtual Machine

21 Quelle: http://developer.android.com/tools/testing/testing_android.html

Details

Seiten
97
Jahr
2013
ISBN (eBook)
9783668133532
ISBN (Buch)
9783668133549
Dateigröße
2.4 MB
Sprache
Deutsch
Katalognummer
v314757
Institution / Hochschule
Hochschule der Medien Stuttgart
Note
1,7
Schlagworte
android continuous integration test automatisiertes testen automatisierte tests jenkins

Autor

Teilen

Zurück

Titel: Continuous Integration und automatisierte Tests für Android