Zielen Sie auf ein App-Beispiel

Diese Kategorie von Instrumentierungstests unterscheidet sich nicht wesentlich von denen, die auf normale Android-Anwendungen abzielen. Es ist zu beachten, dass die Testanwendung, die die Instrumentierung enthielt, mit demselben Zertifikat signiert sein muss wie die Anwendung, auf die sie abzielt.

Beachten Sie, dass in dieser Anleitung davon ausgegangen wird, dass Sie bereits über einige Kenntnisse im Quellbaum-Workflow der Plattform verfügen. Wenn nicht, lesen Sie bitte die Anforderungen . Das hier behandelte Beispiel ist das Schreiben eines neuen Instrumentierungstests, bei dem das Zielpaket auf ein eigenes Testanwendungspaket eingestellt ist. Wenn Sie mit dem Konzept nicht vertraut sind, lesen Sie bitte die Einführung zum Plattformtest durch.

In diesem Leitfaden wird der folgende Test als Beispiel verwendet:

  • Frameworks/Base/Pakete/Shell/Tests

Es empfiehlt sich, zunächst den Code durchzublättern, um sich einen groben Eindruck zu verschaffen, bevor Sie fortfahren.

Entscheiden Sie sich für einen Quellstandort

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

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

Manifestdatei

Genau wie eine normale Anwendung benötigt jedes Instrumentierungstestmodul eine Manifestdatei. Wenn Sie die Datei AndroidManifest.xml nennen und sie neben Android.mk für Ihr Test-Tmodul bereitstellen, wird sie automatisch vom BUILD_PACKAGE Kern-Makefile eingebunden.

Bevor Sie fortfahren, wird dringend empfohlen, zunächst die App-Manifest-Übersicht durchzugehen.

Dies gibt einen Überblick über die grundlegenden Komponenten einer Manifestdatei und ihre Funktionalitäten.

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

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 Name des Anwendungspakets: 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 vom zu testenden Anwendungspaket ist, muss ein anderer Paketname verwendet werden: Eine gängige Konvention besteht darin, ein Suffix .test hinzuzufügen.

Darüber hinaus ist dieses package dasselbe wie das, was ComponentName#getPackageName() zurückgibt, und auch dasselbe, das Sie für die Interaktion mit verschiedenen pm Unterbefehlen über adb shell verwenden würden.

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

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

Dies ist für alle Instrumentierungstests 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 gesetzt. Wenn die Instrumentierung über den Befehl am instrument aufgerufen wird, startet das Framework den Prozess com.android.shell neu und fügt Instrumentierungscode zur Testausführung in den Prozess ein. Dies bedeutet auch, dass der Testcode Zugriff auf alle Klasseninstanzen hat, die in der getesteten Anwendung ausgeführt werden, und möglicherweise den Zustand manipulieren kann, abhängig von den bereitgestellten Test-Hooks.

Einfache Konfigurationsdatei

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

Komplexe Konfigurationsdatei

Für komplexere Tests müssen Sie außerdem eine Testkonfigurationsdatei für Androids Testumgebung Trade Federation schreiben.

Die Testkonfiguration kann spezielle Geräte-Setup-Optionen und Standardargumente zur Bereitstellung der Testklasse angeben.

Die neueste Version der Konfigurationsdatei für die Beispiel-Gerrit-Änderung kann unter Frameworks/base/packages/Shell/tests/AndroidTest.xml abgerufen werden

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 mit einem angegebenen target_preparer auf dem Zielgerät zu installieren. Den Entwicklern in Trade Federation stehen viele Zielvorbereiter 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 sowie das Test-Runner-Framework, in diesem Fall JUnit.

Weitere Informationen zu Testmodulkonfigurationen finden Sie hier

JUnit4-Funktionen

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

Der aktuelle Quellcode für die Beispiel-Gerrit-Änderung kann unter folgender Adresse abgerufen werden: Frameworks/Base/Packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java

Während Testmuster in der Regel spezifisch für Komponententeams sind, gibt es einige allgemein nützliche Nutzungsmuster.

@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 Annotationen, 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 gab eine Testgröße für die gesamte Testklasse an: Alle zu dieser Testklasse hinzugefügten Testmethoden erben diese Annotation zur Testgröße. Klassenaufbau vor dem Test, Abbau nach dem Test und Abbau der Klasse nach dem Test: ähnlich den Methoden setUp und tearDown in JUnit4. Test werden zum Kommentieren des eigentlichen Tests verwendet.

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

Die @Before Annotation wird von JUnit4 für Methoden verwendet, um die Einrichtung vor dem Test durchzuführen. Obwohl in diesem Beispiel nicht verwendet, 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 vor der Ausführung aller Tests in einer Testklasse ein Setup durchzuführen und anschließend ein Teardown durchzuführen. Beachten Sie, dass die Setup- und Teardown-Methoden für den Klassenbereich statisch sein müssen.

Was die Testmethoden betrifft, so müssen sie im Gegensatz zu früheren Versionen von JUnit den Methodennamen nicht mehr mit test beginnen, sondern jede von ihnen muss mit @Test annotiert 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 erfordern, ist es nicht mehr erforderlich, Context Instanzen über getContext() oder getTargetContext() über Basisklassenmethoden abzurufen; Stattdessen verwaltet der neue Testläufer sie über InstrumentationRegistry , wo vom Instrumentierungsframework erstellte Kontext- und Umgebungseinstellungen gespeichert werden. Über diese Klasse können Sie auch Folgendes aufrufen:

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

Lokal erstellen und testen

Für die häufigsten Anwendungsfälle verwenden Sie Atest .

Befolgen Sie bei komplexeren Fällen, die eine umfassendere Anpassung erfordern, die Anweisungen zur Instrumentierung .