Emma ist ein Code Coverage Tool, u.a. auch für Android. Damit lassen sich Auswertungen erstellen, welcher Code während der Programmausführung auch wirklich ausgeführt wurde. Emma benötigt dazu sogenannten instrumentieren Code. Zum Instrumentieren wird ein Virtual Device oder ein gerootetes Gerät benötigt. Das hängt mit den benötigten Berechtigungen zusammen. Da nicht jeder Entwickler ein gerootetets Gerät hat, instrumentieren wir hier ein Virtual Device mit dem Namen "Virtual".
Das Virtual Device benötigt außerdem eine (emulierte, zusätzliche) SD-Karte. Emma schreibt die Daten auf diese SD-Karte, da keine Berechtigungen für /data vorhanden sind, wohin Emma üblicherweise schreibt.
Los geht's. Einmalig eine Datei für die "SD-Karte" erzeugen:
> %ANDROID_SDK%\tools\mksdcard 256M %ANDROID_SDK%\tools\mysdcard
Das Virtual Device starten:
> %ANDROID_SDK%\tools\emulator -avd Virtual -sdcard %ANDROID_SDK%\tools\mysdcard
Virtual ist dabei der Name des Virtual Devices. Als nächstes wird eine ant build.xml für das eigentliche, zu untersuchende Projekt erzeugt (sofern noch nicht vorhanden). Basis dafür ist die AndroidManifest.xml Datei:
> %ANDROID_SDK%\tools\android update project --path . --target android-8
--path und --target müssen natürlich angepasst werden.
Ins Testprojekt wechseln, und dort ebenfalls die ant build.xml erzeugen:
> %ANDROID_SDK%\tools\android update test-project --path . --main ..
Jetzt können wir endlich instrumentieren und Emma ausführen:
> ant -Demma.dump.file=/sdcard/coverage.ec emma instrument install test
Aber nach kurzer Zeit erscheint:
test:
[echo] Running tests ...
[exec] Syntax error: Bad substitution
Häh ?
Ursache ist ein Fehler in der verwendeten build.xml (hier: rev14) die Bestandteil des Android-SDKs ist. Tritt der Fehler auf, so muss in %ANDROID_SDK%\tools\ant\build.xml im Abschnitt
<macrodef name="run-tests-helper">
<attribute name="emma.enabled" default="false" />
...
<arg value="${manifest.package}/${test.runner}" />
</exec>
</sequential>
</macrodef>
durch
<macrodef name="run-tests-helper">
<attribute name="emma.enabled" default="false" />
...
<arg value="${tested.manifest.package}/${test.runner}" />
</exec>
</sequential>
</macrodef>
ersetzt werden.
Nach der Korrektur weiter mit dem nächsten Versuch:
> ant -Demma.dump.file=/sdcard/coverage.ec -Dtested.manifest.package=xxx.xxx.xxx emma instrument install test
Kommt es zu diesem Fehler
test:
[echo] Running tests ...
[exec] INSTRUMENTATION_STATUS: id=ActivityManagerService
[exec]
[exec] INSTRUMENTATION_STATUS: Error=Unable to find instrumentation info fo
r: ComponentInfo{xxx.xxx.xxx/android.test.InstrumentationTestRunne
r}
[exec] INSTRUMENTATION_STATUS_CODE: -1
[exec] android.util.AndroidException: INSTRUMENTATION_FAILED:xxx.xxx.xxx /android.test.InstrumentationTestRunner
so liegt es daran, dass die Projekt und die Test-Projekt Sourcen das gleiche Package verwenden. Zum Instrumentieren sollten die Test-Projekt Sourcen in einem xxx.xxx.test Package sein.
Next try.
> ant -Demma.dump.file=/sdcard/coverage.ec -Dtested.manifest.package=xxx.xxx.xxx.test instrument install test
Nach einiger (?) Zeit sollte in der Kommandozeile folgendes erscheinen:
[exec] Generated code coverage data to /sdcard/coverage.ec
[echo] Downloading coverage file into project directory...
[exec] 24 KB/s (3809 bytes in 0.151s)
[echo] Extracting coverage report...
[echo] Cleaning up temporary files...
[echo] Saving the report file in .../coverage/coverage.html
Heureka !
Das Ergebnis kann man sich dann mit
> start coverage\coverage.html
anzeigen lassen.
Tipp 1: ist die Code Coverage für das eigentliche Projekt 0%, so werden dort nicht die instrumentierten Dateien verwendet. Ich habe mir damit beholfen, dass ich meine <Projekt>-instrumented.apk nach <Projekt>-debug.apk umbenannt und installiert habe. Ich kann es mir nur so erklären, dass noch eine <Projekt>-debug.apk auf dem System vorhanden ist, und aufgrund des Dateinamens im Classpath vor der <Projekt>-instrumented.apk gefunden wird.
Tipp 2: die Code Coverage für das Testprojekt wird nicht richtig angezeigt. Ursache ist, dass für die Auswertung auf die Datei coverage.em im Hauptrojekt zugegriffen wird. Hier fehlen aber die Informationen über das Testtrojekt. Einen funktionierenden Workaround dafür habe ich nicht gefunden, falls jemand eine Lösung findet würde ich mich über ein kleines How-To freuen.
Weiterführende Infos gibt es auf android developers.