Blog

Wie Sie Android Instrumentation Tests mit ProGuard durchführen

Barend Garvelink

Barend Garvelink

Aktualisiert Oktober 22, 2025
4 Minuten

Die App, an der ich arbeite, verfügt über eine umfangreiche, automatisierte Testsuite, die mit Instrumentation und Robotium erstellt wurde. Dabei handelt es sich um White-Box-Tests. Sie kennen die Java-Klassen, aus denen die getestete Anwendung besteht. Das bedeutet, dass wir die Tests nach dem ProGuardingunserer Anwendung nicht mehr ausführen konnten. Ich habe noch nie erlebt, dass ProGuard einen funktionierenden Code beschädigt hat, nachdem ich die richtigen Ausnahmen eingerichtet hatte. Dennoch ist es etwas fragwürdig, eine umfangreiche automatisierte Testsuite zu haben und sie nicht auf die APK anzuwenden, die wir an den Play Store liefern.

ProGuard und Instrumentierungstests

Eine mögliche Umgehung ist die Verwendung des UIAutomator-Frameworks, das diese Einschränkung nicht hat. Es gibt mehrere Gründe, warum wir das nicht tun konnten: Es erfordert API-Level 16 (Jelly Bean), unsere App unterstützt API 8 (Froyo) als Mindest-SDK-Version. Außerdem hatten wir unsere Testsuite bereits eingerichtet und es erschien uns nicht sinnvoll, sie von Grund auf neu zu schreiben. Stattdessen haben wir Folgendes getan.

Die Grundidee könnte nicht einfacher sein. Sie können die Tests nicht mit einem verschleierten Paket ausführen? Verschlüsseln Sie die Tests auf die gleiche Weise! ProGuard verfügt über die -applymapping Direktive, die in Verbindung mit der -printmapping zusammenarbeitet, damit Sie ein Obfuskations-Mapping wiederverwenden können. Wenn Sie die Standard-Android-Ant-Build-Skripte verwenden, müssen Sie ein paar Dinge ändern:

Aktualisieren Sie die ProGuard-Konfiguration des Hauptprojekts

Wenn Sie es nicht bereits für retrace hinzugefügt haben, fügen Sie die Direktive -printmapping in die ProGuard-Konfiguration Ihres Hauptprojekts ein.

Generates bin/proguard-mapping.txt
-printmapping proguard-mapping.txt

Aktualisieren Sie die ProGuard-Konfiguration des Testprojekts

Ihr Testprojekt benötigt zwei Dinge: die Direktive -applymapping, um die Mapping-Datei des Hauptprojekts wiederzuverwenden, und so viele -injars Direktiven, die Sie benötigen, um alle einfachen Versionen Ihres Programmcodes und Ihrer Bibliotheken hinzuzufügen.

[code language="bash"]
Reuse the main project's ProGuard mapping
-applymapping ../mainproject/bin/proguard-mapping.txt
# ProGuard is automatically fed the obfuscated code of the main
# project. It also needs the plain version:
-injars ../mainproject/bin/classes
-injars ../mainproject/libs/android-support-v4.jar
[/code]

Möglicherweise müssen Sie einige -dontwarn-Direktiven hinzufügen. Ich wurde vor einer fehlenden finish() -Methode für meine Aktivitäten gewarnt, die zur Laufzeit nie ein Problem darstellen wird, da sie in der Basisklasse enthalten ist.

Stellen Sie sicher, dass Ihre Tests geeignet sind

Einige unserer Robotium-Tests beziehen sich auf Aktivitätsklassen durch ihren einfachen Namen, z.B.:

[code language="java"]
private void goBackBackBackUntilHome() {
while ( !"MainActivity".equals(solo.getCurrentActivity().getClass().getSimpleName()) ) {
// sleep a bit and guard against infinite loop
solo.goBack();
}
}
[/code]

ProGuard erkennt dies nicht als Klassenreferenz und wandelt sie nicht um. Eine der folgenden Alternativen wird funktionieren:

[code language="java"]
// Using a class literal
private void goBackBackBackUntilHome() {
while ( !MainActivity.class.isInstance(solo.getCurrentActivity()) ) {
// sleep a bit and guard against infinite loop
solo.goBack();
}
}
// Using a fully qualified class name
private void goBackBackBackUntilHome2() {
while ( !"com.myapp.MainActivity".equals(solo.getCurrentActivity().getClass().getName()) ) {
// sleep a bit and guard against infinite loop
solo.goBack();
}
}
[/code]

Wenn Sie außerdem die Klassennamen von Aktivitäten protokollieren, um die Diagnose von Testfehlern zu erleichtern, sollten Sie jetzt auch deren Titel protokollieren.

Code-Signierung aktivieren

Beide APK-Dateien müssen mit demselben Schlüssel signiert sein, damit die Tests ausgeführt werden können. Sie könnten Ihren eigentlichen Release-Schlüssel verwenden, aber ich würde Ihnen davon abraten, diesen Schlüssel so leichtfertig zu verwenden. Konfigurieren Sie Ihr Projekt stattdessen so, dass es den Android-Debug-Schlüssel verwendet. Wenn es an der Zeit ist, eine Version im Play Store zu veröffentlichen, entfernen Sie einfach die bestehende Signatur aus der APK-Datei und signieren sie neu, indem Sie sie mit Ihrem Produktionsschlüssel neu ausrichten.

Um mit dem Debug-Schlüssel zu signieren, fügen Sie die folgenden vier Zeilen in die Datei ant.properties sowohl im Hauptprojekt als auch im Testprojekt ein:

[code language="java"]
key.store=${user.home}/.android/debug.keystore
key.alias=androiddebugkey
key.store.password=android
key.alias.password=android
[/code]

Holen Sie sich die Ameise, um die Projekte richtig zu verketten

Wenn Sie ein beliebiges Build-Ziel auf dem Testprojekt ausführen, wird es automatisch an das getestete Projekt delegiert und auch dieses gebaut. Leider gibt es ein Versehen in der Build-Datei von Google (sdk rev 22 / tools rev 18). Wenn Sie einen Release-Build des Testprojekts ausführen, wird ein Debug-Build des Hauptprojekts erstellt. Sie können dies mit einem kleinen Missbrauch der Ant-Eigenschaften leicht umgehen:

user@machine test-project$ ant release -Dtested.project.target=release

Dies führt dazu, dass beide Projekte im Release-Modus erstellt werden und die gesamte Einrichtung nun funktioniert.

Bonustipp: Verwenden Sie -Dtested.project.target=help, um die Erstellung des Hauptprojekts zu überspringen, wenn Sie nur Ihre Tests geändert haben.

Führen Sie Ihre Tests durch

Ich bin mir nicht sicher, ob der Befehl ant test nach all dem noch funktioniert. Wir hatten bereits Shell-Skripte, die den Befehl adb install und adb shell am instrument direkt und nicht über Ant aufrufen. Vielleicht brauchen Sie etwas Ähnliches.

Verfasst von

Barend Garvelink

Contact

Let’s discuss how we can support your journey.