Upload
open-knowledge-gmbh
View
294
Download
1
Tags:
Embed Size (px)
DESCRIPTION
Nach dem Release ist es nicht vorbei Speaker: Arne Limburg Die Tests vor der ersten Veröffentlichung einer Android-App im Play Store fallen in der Regel recht ausgiebig aus. Aber was kommt danach? Wie kann eine mobile App geeignet gewartet und dauerhaft gepflegt werden? Wie können Probleme und Optimierungspotenziale nach dem ersten Release erkannt werden? Und wie geht man damit um, wenn man parallel die Weiterentwicklung der App vorantreiben will? In der Session wird gezeigt, wie man über geeignetes Crash-Reporting und proaktives App-Feedback auch bei Bugs eine optimale User Experience erzielen kann. Der Schwerpunkt liegt dabei darauf, wie durch gezielte Testautomatisierung zusätzlich Regressionssicherheit in der Weiterentwicklung erreicht werden kann. Denn nichts ist schlimmer als eine negative Bewertung im Play Store.
Citation preview
Arne Limburg | open knowledge GmbH
Automatisiertes Testen in Android @ArneLimburg
@_openknowledge
Meine PersonArne LimburgHead of Architecture and Technologyopen knowledge GmbH
@ArneLimburg@_openknowledge
www.openknowledge.de
Diese Session startet wo andere aufhören...
Wie geht es weiter?
Wie geht es weiter?
• Nutzerfeedback?• Probleme?• Bugs?
Informationsquellen
• Nutzerfeedback• Statistiken• Bug-Reports• Third-Party-Libraries
Informationsquellen
• Nutzerfeedback• Statistiken• Bug-Reports• Third-Party-Libraries
Nutzerfeedback
Alpha- und Beta-Tests
• Auswahl von Testgruppe– Google-Gruppe oder– Google+ Community
• Veröffentlichung als Alpha- oder Beta-APK• Download über Play Store• In-App-Billing-Tester
– Separate Angabe der Google-Konten im Play Store (max. 400)
Testen von In-App-Billing
• Anlage von Test-Konten über Developer – Google-Gruppe oder– Google+ Community
• Veröffentlichung als Alpha- oder Beta-APK• Download über Play Store
Informationsquellen
• Nutzerfeedback• Statistiken• Bug-Reports• Third-Party-Libraries
Informationsquellen
• Nutzerfeedback• Statistiken• Bug-Reports• Third-Party-Libraries
Statistiken
Statistiken
Informationsquellen
• Nutzerfeedback• Statistiken• Bug-Reports• Third-Party-Libraries
Abstürze & ANRS
Stacktraces
ANRS
Application not responding.
Fazit – Android Developer Console
• Vieles Out-Of-The-Box• Grenzen schnell erreicht
– Keine Zuordnung von Fehler zu Gerät und/oder Version
– Bei Crashes nur Stacktraces (keine weiteren Logs)
Informationsquellen
• Nutzerfeedback• Statistiken• Bug-Reports• Third-Party-Libraries
Informationsquellen
• Nutzerfeedback• Statistiken• Bug-Reports• Third-Party-Libraries
Third-Party Crash Reports
• ACRA• BugSense• HockeyApp• ...
ACRA @ReportsCrashes(formKey = "…") public class MyApplication extends Application { public void onCreate() { ACRA.init(this); super.onCreate(); } … }
ACRA @ReportsCrashes(formKey = "…" mode = … ) public class MyApplication extends Application { … }
ACRA - Zusatzinformationen
public class SomeClass { public void somewhere() { ErrorReporter.getInstance() .putCustomData("myVariable", "myValue"); } … }
ACRA – Senden ohne Absturz
public class SomeClass { public void somewhere(Exception e) { ErrorReporter.getInstance() .handleException(e); } … }
ACRA – Senden ohne Absturz
public class SomeClass { public void somewhere(Exception e) { ErrorReporter.getInstance() .handleSilentException(e); } … }
ACRA – Senden ohne Absturz
public class SomeClass { public void somewhere(Exception e) { ErrorReporter.getInstance() .handleSilentException(e); } … }
Ideal während Alpha- und Beta-Testing
Testen von User Experience
Fazit – Third-Party-Crash-Reports
• Nutzer-Feedback direkt (und nicht über Google)
• Mehr Informationen• Sinnvollere Informationen
Tipp: Belohnungssystem für Bewertung
Rating aus der App heraus public void someMethod() { Uri uri = Uri.parse("market://details?id=“ + APP_NAME); Intent intent = new Intent(Intent.ACTION_VIEW, uri); startActivity(intent); }
Aufgaben
• Feature-Requests• User Experience
Ergebnisse einarbeiten
• Bugfixing• Weiterentwicklung
Herausforderungen
• Vielfalt der Geräte• Bildschirmauflösung• Eingabemethode
• Capabilities
• Vielfalt der Umwelteinflüsse• Umgebung (Netz, Batterie, Standort)• Nutzerverhalten
Was tun?
Rechne mit allem!
Rechne mit nichts!
Testen, Testen, Testen!
Testen
• Konzentration auf das Wesentliche– Geräte– Android-Versionen– Länder– Operatoren
• Test-Automatisierung
Herausforderungen
• Vielfalt der Geräte• Bildschirmauflösung• Eingabemethode
• Capabilities
• Vielfalt der Umwelteinflüsse• Umgebung (Netz, Batterie, Standort)• Nutzerverhalten
Was tun?
Rechne mit allem!
Rechne mit nichts!
Testen, Testen, Testen!
Testen
• Konzentration auf das Wesentliche– Geräte– Android-Versionen– Länder– Operatoren
• Test-Automatisierung
Unit-Tests
Testen - Agenda
1
2
3
4
Funktionstests
Abnahme- und Regressionstests
Stresstests
Unit-Tests
Unit-Testing
„A unit is the smallest testable part of an application.“http://en.wikipedia.org/wiki/Unit_testing
Ziel von Unit-Testing
• korrekte Funktionsweise von kleinen Einheiten der Software (Testen einzelner Methoden)
• Automatisch• Regelmäßig (Continuous Integration)• Regressionssicher
Android Testing Framework
• JUnit-Unterstützung für On-Device-Testing
• Oberklassen zum Testen von Android-Komponenten
• Activity• Content-Provider• Service• …
Mock-Kontexte
• MockContext• Alle Methoden werfen Exception
• IsolatedContext• Isolation vom Device• Datenbank- und Datei-Operationen möglich
• RenamingDelegatingContext• Kommunikation mit dem Device möglich• Datenbank- und Datei-Operationen werden
umgeleitet
Android Testing - Architektur
Unit-Test-Klassenhierarchie
junit.framework.TestCase
AndroidTestCase InstrumentationTestCase
Package android.test
ApplicationTestCase
LoaderTestCase
ProviderTestCase2
ServiceTestCase
ActivityTestCase
ActivityUnitTestCase
ActivityInstrumentationTestCase2
PoviderTestCase2
• Testen eines isolierten Content-Providers• Verwendung von IsolatedContext• Bereitstellen eines MockContentResolvers
API
setContext(Context) (von AndroidTestCase)
getMockContentResolver()getProvider
ProviderTestCase2public class PositionProviderTest extends ProviderTestCase2<PositionProvider> {
public PositionProviderTest() { super(PositionProvider.class, PositionProvider.AUTHORITY); }
public void testInsert() { … }
ServiceTestCase
• Standardmäßig mit „echtem“ Context und MockApplication
• Herausforderung: Testen von Threading
APIsetApplication(Application)setContext(Context) (von AndroidTestCase)
startService(Intent)bindService(Intent)
ServiceTestCasepublic class UpdaterServiceTest extends ServiceTestCase<UpdaterService> {
public UpdaterServiceTest() { super(UpdaterService.class); }
public void testStartService() { … }}
Code Diving ...
ActivityUnitTestCase
• Leitet von InstrumentationTestCase ab• Isoliertes Testen einer Activity
API (Auszug)getStartedActivityIntent()getStartedActivityRequest()getRequestOrientation()isFinishedCalled()
ActivityUnitTestCasepublic class Positio…ActivityUnitTest extends ActivityUnitTestCase<Position…Activity> {
public PositionOverviewActivityUnitTest() { super(PositionOverviewActivity.class); }
public void testOnListItemClick() { … }}
Code Diving ...
Unit-Tests
• Herausforderung: Umgang mit Abhängigkeiten
• Klassisches Vorgehen: Erstellen von Mocks• On-Device: Mock-Implementierungen des
Android Testing Frameworks• Off-Device: Gängige Java-Mocking-
Frameworks (EasyMock, Mockito, ...)
Off-Device-Testing
• Herausforderung: Android ≠ Java
java.lang.RuntimeException: Stub!
Off-Device– Instantiieren– Mocking via Java-Mocking-Frameworks– Zugriff auf Android-Interna
• Lösung: Robolectric
Robolectric
• Instantiieren von Android-Klassen• Shadowing• Zugriff auf Resourcen• ...
Robolectric@RunWith(RobolectricTestRunner.class) public class PositionOverviewActivityTest {
@Test public void onItemClick() { … }
…}
Robolectric@RunWith(RobolectricTestRunner.class) public class PositionOverviewActivityTest {
@Test public void onItemClick() { … }
…}
Robolectric
@Test public void onItemClick() { … ShadowActivity a = shadowOf(activity); Intent startedIntent = a.getNextStartedActivity(); … }
Code Diving ...
Continuous Integration
• Regelmäßiges Bauen und Testen (CI-Server)
z.B. Jenkins
• Voraussetzung: Automatisiertes Bauen und Testen
Ant, Maven oder Gradle
• Zusatzfeature: Code-Abdeckung mit EMMA
Unit-Tests
Agenda
1
2
3
4
Funktionstests
Abnahme- und Regressionstests
Stresstests
Unit-Tests
Funktionstests
Funktionstests• Testen der Interaktion mit der Umgebung• Testaufbau
• UI-Verhalten• Klickpfade• State-Saving / -Restoring
• Testinhalt• Änderung der Konfiguration (Orientierung, Sprache,
Tastatur, Location)• Änderung der Ressourcen (Batterie, Netzwerk,
Bluetooth, GPS• Eingehender Anruf / SMS
• Tool: Auch Android JUnit
Unit-Test-Klassenhierarchie
junit.framework.TestCase
AndroidTestCase InstrumentationTestCase
Package android.test
ApplicationTestCase
LoaderTestCase
ProviderTestCase2
ServiceTestCase
ActivityTestCase
ActivityUnitTestCase
ActivityInstrumentationTestCase2
InstrumentationTestCase
• API (Auszug)
<T> T launchActivity(String, Class<T>, Bundle)<T> T launchActivityWithIntent(String, Class<T>, Intent)void sendKeys(String)void sendKeys(int…)void sendRepeatedKeys(int…)Instrumentation getInstrumentation()
Instrumentation
• API (Auszug)
ActivityMonitor addMonitor(…)Activity waitForMonitor(…)Activity waitForMonitorWithTimeout(…)void startActivitySync(…)void sendXXXSync(…)void startPerformanceSnapshot()void endPerformanceSnapshot()void startProfiling()Void stopProfiling()
ActivityInstrumentationTestCase2
• Leitet von InstrumentationTestCase ab• Testen von UI-Verhalten
Testen eines gesamten Worksflows• Erzeugen von TouchEvents mit TouchUtils oder über performClick()
• Überprüfen von Layout mit ViewAsserts• Eventuell Verwendung von Third-Party-
Framework (Robotium)
ActivityInstrumentationTestCase2
public class Position…ActivityUiTest extends ActivityInstrumentationTestCase2<Pos…ity> {
public PositionOverviewActivityUiTest() { super(PositionOverviewActivity.class); }
public void testClickOnList() { … }}
Code Diving ...
ActivityUnitTestCase vs.ActivityInstrumentationTestCase2
ActivityUnitTestCase• Reines Testen des
Codes• Kein Test des UI-
Verhaltens• Kein Test des
Workflow-Verhaltens
ActivityInstr…TestCase2• Testen des UI-
Verhaltens• Testen des Workflow-
Verhaltens
Robotium
• Selenium nur für Android• Baut auf Instrumentation auf• Weniger komplex zu bedienen• Black-Box-Testing möglich
Espresso
• Weiterentwicklung von Robotium
onView(withId(R.id.button_simple)) .perform(click());
onView(withId(R.id.text_simple)) .check(matches( withText("Hello Espresso!")));
Code Diving ...
Android Emulator fernsteuern
• Steuerung von Geo-Koordinaten, Telefonie, Netzwerk (Geschwindigkeit, Delay), Batterie, SMS, Sensoren
• DDMS-Perspektive in Eclipse• Verbinden via TelnetBeispiel:
telnet localhost 5554
Continuous Integration
Best Practice• Funktionstests selten ausführen• Klassifizierung von Tests
@SmallTest – „Echter“ Unit-Test (ActivityUnitTest)
@MediumTest– Test einer Komponente mit Umgebung
@LargeTest– Workflow-Test (gesamter Use-Case)
Unit-Tests
Agenda
1
2
3
4
Funktionstests
Abnahme- und Regressionstests
Stresstests
Funktionstests
Abnahme- und Regressionstests
MonkeyRunner
Creative Commons by Simon Englisch
MonkeyRunner
• Python / Jython• Testen kompletter Use-Cases• Vergleichen der Ergebnisse über
Bildschirm-Fotos• Paralleles Testen verschiedener
Devices und Auflösungen via Scripting
MonkeyRunnerMonkeyRunner APIvoid alert(…), integer choice(…), string input(…)void sleep(…)MonkeyDevice waitForConnection(…)
MonkeyDevice API (Auszug)void installPackage(…)void startActivity(…)Void broadcastIntent(…)void drag(…), void press(…), void touch(…), void type(…) MonkeyImage takeSnapshot()
MonkeyImage API (Auszug)MonkeyImage getSubImage(…), boolean sameAs(…), void writeToFile(…)
Unit-Tests
Agenda
1
2
3
4
Funktionstests
Abnahme- und Regressionstests
Stresstests
Abnahme- und Regressionstests
Stresstests
Würden Sie einen Affen mit Ihrem Telefon spielen lassen?
© Rex Features
Monkey
• Schicken zufälliger Events• Anzahl und Geschwindigkeit
konfigurierbar• Reihenfolge reproduzierbar (durch
Angabe von seed)• Wahrscheinlichkeit einzelner Event-
Arten konfigurierbarSuchen von spezifischen Bugs
Unit-Tests
Agenda
1
2
3
4
Funktionstests
Regressionstests
StresstestsStresstests
Fazit - Testing
• Unit-Tests• Off Device (Robolectric)• On Device (Android Testing Framework)• Regelmäßig (Continuous Integration) mit Simulator• Vor der Auslieferung mit echten Geräten
• Funktionale Tests• UI-Interaktion• Gesamter Workflow (automatisiert)
• Regressionstests (MonkeyRunner)• Stresstests (Monkey)
Vielen Dank für Ihre Zeit.
Kontakt:
open knowledge GmbHBismarckstr. 1326122 Oldenburg
@ArneLimburg @_openknowledge
Q&A