Ausrichtung auf ein Anwendungsbeispiel

Diese Kategorie von Instrumentierungstests unterscheidet sich nicht wesentlich von denen, die auf die regulären Android-Anwendungen abzielen. Beachten Sie, dass die Testanwendung, die die Instrumentierung enthält, mit demselben Zertifikat signiert werden muss wie die Anwendung, auf die sie abzielt.

Beachten Sie, dass in diesem Handbuch davon ausgegangen wird, dass Sie bereits über Kenntnisse im Arbeitsablauf der Plattform-Quellstruktur verfügen. Wenn nicht, siehe Anforderungen . Das hier behandelte Beispiel schreibt einen neuen Instrumentierungstest mit einem Zielpaket, das in einem eigenen Testanwendungspaket festgelegt ist. Wenn Sie mit dem Konzept nicht vertraut sind, lesen Sie bitte die Einführung zum Plattformtest .

Dieser Leitfaden verwendet den folgenden Test als Beispiel:

  • Frameworks/Basis/Pakete/Shell/Tests

Es wird empfohlen, zuerst den Code zu durchsuchen, um einen groben Eindruck zu bekommen, bevor Sie fortfahren.

Entscheidung für einen Quellort

Da der Instrumentierungstest auf eine Anwendung abzielt, besteht die Konvention darin, den Testquellcode in einem tests unter dem Stamm Ihres Komponentenquellverzeichnisses in der Plattformquellstruktur zu platzieren.

Weitere Diskussionen zum Quellstandort finden Sie im End-to-End-Beispiel für selbstinstrumentierende Tests .

Manifest-Datei

Genau wie eine normale Anwendung benötigt jedes Instrumentierungstestmodul eine Manifestdatei. Wenn Sie die Datei als AndroidManifest.xml und neben Android.mk für Ihr Test-T-Modul bereitstellen, wird sie automatisch vom BUILD_PACKAGE Core-Makefile eingefügt.

Bevor Sie fortfahren, wird dringend empfohlen, zuerst die App-Manifest-Übersicht durchzugehen .

Dies gibt einen Überblick über grundlegende Komponenten einer Manifestdatei und deren Funktionalitäten.

Auf die neueste Version der Manifestdatei für die Beispiel-Gerrit-Änderung kann zugegriffen werden unter: https://android.googlesource.com/platform/frameworks/base/+/master/packages/Shell/tests/AndroidManifest.xml

Der Einfachheit halber ist hier ein Schnappschuss enthalten:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

    <application>
        <uses-library android:name="android.test.runner" />

        <activity
            android:name="com.android.shell.ActionSendMultipleConsumerActivity"
            android:label="ActionSendMultipleConsumer"
            android:theme="@android:style/Theme.NoDisplay"
            android:noHistory="true"
            android:excludeFromRecents="true">
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
        </activity>
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
        android:targetPackage="com.android.shell"
        android:label="Tests for Shell" />

</manifest>

Einige ausgewählte Anmerkungen zur Manifestdatei:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

Das package ist der Anwendungspaketname: Dies ist die eindeutige Kennung, die das Android-Anwendungsframework verwendet, um eine Anwendung (oder in diesem Zusammenhang: Ihre Testanwendung) zu identifizieren. Jeder Benutzer im System kann nur eine Anwendung mit diesem Paketnamen installieren.

Da es sich um ein Testanwendungspaket handelt, das unabhängig von dem zu testenden Anwendungspaket ist, muss ein anderer Paketname verwendet werden: Eine gängige Konvention besteht darin, ein Suffix .test .

Darüber hinaus ist dieses package dasselbe wie das, was ComponentName#getPackageName() zurückgibt, und auch dasselbe, das Sie verwenden würden, um mit verschiedenen pm sub-Befehlen über adb shell zu interagieren.

Bitte beachten Sie auch, dass der Paketname zwar normalerweise den gleichen Stil wie ein Java-Paketname hat, aber eigentlich nur sehr wenig damit zu tun hat. Mit anderen Worten, Ihr Anwendungs- (oder Test-) Paket kann Klassen mit beliebigen Paketnamen enthalten, obwohl Sie sich andererseits für die Einfachheit entscheiden und Ihren Java-Paketnamen der obersten Ebene in Ihrer Anwendung oder Ihrem Test identisch mit dem Namen des Anwendungspakets haben könnten.

<uses-library android:name="android.test.runner" />

Dies ist für alle Instrumentationstests erforderlich, da die zugehörigen Klassen in einer separaten Framework-JAR-Bibliotheksdatei gepackt sind und daher zusätzliche Klassenpfadeinträge erforderlich sind, wenn das Testpaket vom Anwendungsframework aufgerufen wird.

android:targetPackage="com.android.shell"

Dadurch wird das Zielpaket der Instrumentierung auf com.android.shell . Wenn die Instrumentierung über einen am instrument aufgerufen wird, startet das Framework den com.android.shell Prozess neu und fügt Instrumentierungscode in den Prozess zur Testausführung ein. Dies bedeutet auch, dass der Testcode Zugriff auf alle Klasseninstanzen hat, die in der zu testenden Anwendung ausgeführt werden, und in der Lage sein kann, den Zustand abhängig von den exponierten Test-Hooks zu manipulieren.

Einfache Konfigurationsdatei

Jedes neue Testmodul muss über eine Konfigurationsdatei verfügen, um das Build-System mit Modulmetadaten, Abhängigkeiten zur Kompilierzeit und Paketierungsanweisungen zu steuern. In den meisten Fällen ist die Soong-basierte Blueprint-Dateioption ausreichend. Einzelheiten finden Sie unter Einfache Testkonfiguration .

Komplexe Konfigurationsdatei

Für komplexere Tests müssen Sie auch eine Testkonfigurationsdatei für die Android-Testumgebung Trade Federation schreiben.

Die Testkonfiguration kann spezielle Geräteeinrichtungsoptionen und Standardargumente angeben, um die Testklasse bereitzustellen.

Auf die neueste Version der Konfigurationsdatei für die Beispiel-Gerrit-Änderung kann zugegriffen werden unter: frameworks/base/packages/Shell/tests/AndroidTest.xml

Der Einfachheit halber ist hier ein Schnappschuss enthalten:

<configuration description="Runs Tests for Shell.">
    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
        <option name="test-file-name" value="ShellTests.apk" />
    </target_preparer>

    <option name="test-suite-tag" value="apct" />
    <option name="test-tag" value="ShellTests" />
    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
        <option name="package" value="com.android.shell.tests" />
        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
    </test>
</configuration>

Einige ausgewählte Anmerkungen zur Testkonfigurationsdatei:

<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
  <option name="test-file-name" value="ShellTests.apk"/>
</target_preparer>

Dadurch wird Trade Federation angewiesen, ShellTests.apk mithilfe eines angegebenen target_preparer auf dem Zielgerät zu installieren. Entwicklern in der Trade Federation stehen viele Target-Vorbereiter zur Verfügung, mit denen sichergestellt werden kann, dass das Gerät vor der Testausführung ordnungsgemäß eingerichtet ist.

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
  <option name="package" value="com.android.shell.tests"/>
  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>

Dies gibt die Trade Federation-Testklasse an, die zum Ausführen des Tests verwendet werden soll, und übergibt das Paket auf dem auszuführenden Gerät und dem Test-Runner-Framework, in diesem Fall JUnit.

Hier finden Sie weitere Informationen zu Testmodulkonfigurationen

JUnit4-Funktionen

Die Verwendung android-support-test Bibliothek als Test-Runner ermöglicht die Übernahme neuer Testklassen im JUnit4-Stil, und die Beispiel-Gerrit-Änderung enthält eine sehr grundlegende Verwendung ihrer Funktionen.

Auf den neuesten Quellcode für die Beispiel-Gerrit-Änderung kann zugegriffen werden unter: frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java

Während Testmuster normalerweise spezifisch für Komponententeams sind, gibt es einige allgemein nützliche Verwendungsmuster.

@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {

Ein wesentlicher Unterschied in JUnit4 besteht darin, dass Tests nicht mehr von einer gemeinsamen Basistestklasse erben müssen; Stattdessen schreiben Sie Tests in einfachen Java-Klassen und verwenden Anmerkungen, um bestimmte Testeinstellungen und Einschränkungen anzugeben. In diesem Beispiel weisen wir an, dass diese Klasse als Android JUnit4-Test ausgeführt werden soll.

Die Annotation @SmallTest hat eine Testgröße für die gesamte Testklasse angegeben: Alle Testmethoden, die dieser Testklasse hinzugefügt wurden, erben diese Testgrößenannotation. Pre-Test-Klassen-Setup, Post-Test-Abbau und Post-Test-Klassen-Abbau: ähnlich den Methoden setUp und tearDown in JUnit4. Die Testanmerkung wird zum Kommentieren des eigentlichen Test verwendet.

    @Before
    public void setup() {
    ...
    @Test
    public void testGetProvider_shouldCacheProvider() {
    ...

Die @Before Anmerkung wird bei Methoden von JUnit4 verwendet, um eine Vortesteinrichtung durchzuführen. Obwohl es in diesem Beispiel nicht verwendet wird, gibt es auch @After für den Teardown nach dem Test. In ähnlicher Weise können die Annotationen @BeforeClass und @AfterClass für Methoden von JUnit4 verwendet werden, um Setup durchzuführen, bevor alle Tests in einer Testklasse ausgeführt werden, und danach Teardown. Beachten Sie, dass die Setup- und Teardown-Methoden im Klassenbereich statisch sein müssen.

Anders als in früheren Versionen von JUnit müssen die Testmethoden den Methodennamen nicht mehr mit test beginnen, sondern müssen alle mit @Test kommentiert werden. Wie üblich müssen Testmethoden öffentlich sein, keinen Rückgabewert deklarieren, keine Parameter annehmen und dürfen Ausnahmen auslösen.

        Context context = InstrumentationRegistry.getTargetContext();

Da die JUnit4-Tests keine gemeinsame Basisklasse mehr benötigen, ist es nicht länger notwendig, Context -Instanzen über getContext() oder getTargetContext() über Basisklassenmethoden zu erhalten; Stattdessen verwaltet der neue Test Runner sie über InstrumentationRegistry , wo Kontext- und Umgebungseinstellungen gespeichert werden, die vom Instrumentierungsframework erstellt wurden. Über diese Klasse können Sie auch Folgendes anrufen:

  • getInstrumentation() : die Instanz der Instrumentation -Klasse
  • getArguments() : die Befehlszeilenargumente, die über -e <key> <value> an ein am instrument übergeben werden

Erstellen und testen Sie lokal

Verwenden Sie für die häufigsten Anwendungsfälle Atest .

Für komplexere Fälle, die umfangreichere Anpassungen erfordern, befolgen Sie die Anweisungen zur Instrumentierung .