Google 致力于为黑人社区推动种族平等。查看具体举措
Diese Seite wurde von der Cloud Translation API übersetzt.
Switch to English

Beispiel für selbstinstrumentierende Tests

Wenn ein Instrumentierungstest gestartet wird, wird sein Zielpaket mit injiziertem Instrumentierungscode neu gestartet und zur Ausführung initiiert. Eine Ausnahme ist, dass das Zielpaket hier nicht das Android-Anwendungsframework selbst sein kann, dh das Paket android , da dies zu einer paradoxen Situation führen würde, in der das Android-Framework neu gestartet werden müsste, was die Systemfunktionen einschließlich der Instrumentierung unterstützt selbst.

Dies bedeutet, dass sich ein Instrumentierungstest nicht zur Ausführung in das Android-Framework, auch bekannt als Systemserver, einfügen kann. Um das Android-Framework zu testen, kann der Testcode nur öffentliche API-Oberflächen oder solche aufrufen, die über die im Quelltextbaum der Plattform verfügbare Android Interface Definition Language AIDL verfügbar gemacht wurden. Für diese Testkategorie ist es nicht sinnvoll, auf ein bestimmtes Paket abzuzielen. Daher ist es üblich, dass solche Instrumente so deklariert werden, dass sie auf ein eigenes AndroidManifest.xml , wie es in einem eigenen <manifest> -Tag von AndroidManifest.xml .

Abhängig von den Anforderungen können Testanwendungspakete in dieser Kategorie auch:

  • Zum Testen erforderliche Bundle-Aktivitäten.
  • Teilen Sie die Benutzer-ID mit dem System.
  • Mit dem Plattformschlüssel signiert sein.
  • Seien Sie eher gegen die Framework-Quelle als gegen das öffentliche SDK kompiliert.

Diese Kategorie von Instrumentierungstests wird manchmal als Selbstinstrumentierung bezeichnet. Hier einige Beispiele für Selbstinstrumentierungstests in der Plattformquelle:

Das hier behandelte Beispiel schreibt einen neuen Instrumentierungstest mit einem Zielpaket, das in einem eigenen Testanwendungspaket festgelegt ist. In diesem Handbuch wird der folgende Test als Beispiel verwendet:

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

Entscheidung für einen Quellort

In der Regel verfügt Ihr Team bereits über ein festgelegtes Muster von Orten zum Einchecken von Code und Orten zum Hinzufügen von Tests. Die meisten Teams besitzen ein einzelnes Git-Repository oder teilen eines mit anderen Teams, verfügen jedoch über ein dediziertes Unterverzeichnis, das den Quellcode der Komponente enthält.

Unter der Annahme , das Stammverzeichnis für die Komponentenquelle ist bei <component source root> , die meisten Komponenten src und tests Ordner unter ihm, und einige zusätzliche Dateien wie Android.mk (oder aufgebrochen in zusätzliche .mk - Dateien), die Manifest - Datei AndroidManifest.xml und die Testkonfigurationsdatei 'AndroidTest.xml'.

Da Sie einen brandneuen Test hinzufügen, müssen Sie wahrscheinlich das tests neben Ihrer Komponente src erstellen und mit Inhalt src .

In einigen Fällen werden in Ihrem Team möglicherweise weitere Verzeichnisstrukturen tests da verschiedene Testsuiten in einzelne Apks gepackt werden müssen. In diesem Fall müssen Sie unter tests ein neues Unterverzeichnis erstellen.

Unabhängig von der Struktur, werden Sie das Bevölkern am Ende tests Verzeichnis oder das neu erstellte Unterverzeichnis mit Dateien ähnlich zu dem, was in instrumentation Verzeichnis in der Probe gerrit ändern. In den folgenden Abschnitten werden die einzelnen Dateien ausführlicher erläutert.

Manifestdatei

Wie bei einer normalen Anwendung benötigt jedes Instrumentierungstestmodul eine Manifestdatei. Wenn Sie die Datei als AndroidManifest.xml und neben Android.mk für Ihr Testmodul Android.mk , wird sie automatisch vom BUILD_PACKAGE Kern-Makefile aufgenommen.

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

Dies gibt einen Überblick über grundlegende Komponenten einer Manifestdatei und deren Funktionen. Siehe das Beispiel unter platform_testing / tests / example / instrumentation / AndroidManifest.xml .

Ein Schnappschuss ist hier zur Vereinfachung enthalten:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />

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

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                     android:targetPackage="android.test.example.helloworld"
                     android:label="Hello World Test"/>

</manifest>

Einige ausgewählte Anmerkungen zur Manifestdatei:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

Das package ist der Name des Anwendungspakets: Dies ist die eindeutige Kennung, mit der das Android-Anwendungsframework eine Anwendung identifiziert (oder in diesem Zusammenhang Ihre Testanwendung). Jeder Benutzer im System kann nur eine Anwendung mit diesem Paketnamen installieren.

Darüber hinaus dieses package ist Attribut das gleiche wie das, was ComponentName#getPackageName() zurückkehrt, und auch die gleiche Sie mit verschiedenen zu interagieren würde pm Unterbefehle über adb shell .

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

android:sharedUserId="android.uid.system"

Dies erklärt, dass dieser apk zur Installationszeit dieselbe Benutzer-ID, dh Laufzeitidentität, wie die Kernplattform zugewiesen werden sollte. Beachten Sie, dass dies davon abhängt, dass die apk mit demselben Zertifikat wie die Kernplattform signiert wird (siehe LOCAL_CERTIFICATE im obigen Abschnitt), es sich jedoch um unterschiedliche Konzepte handelt:

  • Einige Berechtigungen oder APIs sind signaturgeschützt, für die dasselbe Signaturzertifikat erforderlich ist
  • Für einige Berechtigungen oder APIs ist die system des Anrufers erforderlich. Das aufrufende Paket muss die Benutzer-ID für das system freigeben, wenn es sich um ein von der Kernplattform selbst getrenntes Paket handelt
<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="android.test.example.helloworld"

Sie haben vielleicht bemerkt , dass die targetPackage hier das gleiche erklärt wird , wie das package Attribut in dem deklarierten manifest - Tag dieser Datei. Wie in den Testgrundlagen erwähnt , ist diese Kategorie von Instrumentierungstests normalerweise zum Testen von Framework-APIs vorgesehen. Daher ist es für sie nicht sehr aussagekräftig, ein bestimmtes, zielgerichtetes Anwendungspaket zu haben, außer sich selbst.

Einfache Konfigurationsdatei

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

Komplexe Konfigurationsdatei

Für diese komplexeren Fälle müssen Sie auch eine Testkonfigurationsdatei für das Testgeschirr von Android, Trade Federation , schreiben.

In der Testkonfiguration können spezielle Geräte-Setup-Optionen und Standardargumente angegeben werden, um die Testklasse bereitzustellen. Siehe das Beispiel unter /platform_testing/tests/example/instrumentation/AndroidTest.xml .

Ein Schnappschuss ist hier zur Vereinfachung enthalten:

<configuration description="Runs sample instrumentation test.">
  <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
  <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
    <option name="test-file-name" value="HelloWorldTests.apk"/>
  </target_preparer>
  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
  <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
  <option name="test-suite-tag" value="apct"/>
  <option name="test-tag" value="SampleInstrumentationTest"/>

  <test class="com.android.tradefed.testtype.AndroidJUnitTest">
    <option name="package" value="android.test.example.helloworld"/>
    <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="HelloWorldTests.apk"/>
</target_preparer>

Dies weist Trade Federation an, die Datei HelloWorldTests.apk mit einem angegebenen target_preparer auf dem Zielgerät zu installieren. Entwicklern in Trade Federation stehen viele Zielvorbereitungen zur Verfügung, mit denen sichergestellt werden kann, dass das Gerät vor der Testausführung ordnungsgemäß eingerichtet wird.

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
  <option name="package" value="android.test.example.helloworld"/>
  <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 das Test-Runner-Framework, das in diesem Fall JUnit ist.

Weitere Informationen finden Sie unter Testmodul-Konfigurationen .

JUnit4-Funktionen

Die Verwendung der android-support-test Testbibliothek als Testläufer ermöglicht die Übernahme neuer Testklassen im JUnit4-Stil, und die Änderung des Beispielgerrits enthält einige sehr grundlegende Funktionen. Siehe das Beispiel unter /platform_testing/tests/example/instrumentation/src/android/test/example/helloworld/HelloWorldTest.java .

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

@RunWith(JUnit4.class)
public class HelloWorldTest {

Ein wesentlicher Unterschied in JUnit4 besteht darin, dass keine Tests mehr erforderlich sind, um von einer gemeinsamen Basistestklasse zu erben. 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 JUnit4-Test ausgeführt werden soll.

    @BeforeClass
    public static void beforeClass() {
    ...
    @AfterClass
    public static void afterClass() {
    ...
    @Before
    public void before() {
    ...
    @After
    public void after() {
    ...
    @Test
    @SmallTest
    public void testHelloWorld() {
    ...

Die Annotationen @Before und @After werden von JUnit4 für Methoden verwendet, um die Einrichtung vor dem Test und das Herunterfahren nach dem Test durchzuführen. In ähnlicher Weise werden die Annotationen @BeforeClass und @AfterClass für Methoden von JUnit4 verwendet, um das Setup durchzuführen, bevor alle Tests in einer Testklasse ausgeführt werden, und anschließend herunterzufahren. Beachten Sie, dass die Setup- und Teardown-Methoden für den Klassenbereich statisch sein müssen. Anders als in früheren Versionen von JUnit müssen die Testmethoden den Methodennamen nicht mehr mit test , sondern müssen mit @Test . Wie üblich müssen Testmethoden öffentlich sein, keinen Rückgabewert deklarieren, keine Parameter annehmen und dürfen Ausnahmen auslösen.

Wichtig : Die Testmethoden selbst sind mit @Test Annotation versehen. und beachten Sie, dass Tests, die über APCT ausgeführt werden sollen, mit Testgrößen versehen werden müssen: die mit Beispielen versehene Methode testHelloWorld als @SmallTest . Die Annotation kann im Methodenbereich oder im Klassenbereich angewendet werden.

Zugriff auf instrumentation

Obwohl dies im grundlegenden Beispiel für die Hallo-Welt nicht behandelt wird, erfordert ein Android-Test häufig Zugriff auf die Instrumentation : Dies ist die Kern-API-Schnittstelle, die Zugriff auf Anwendungskontexte, Test-APIs für den Aktivitätslebenszyklus und mehr bietet.

Da für die JUnit4-Tests keine gemeinsame Basisklasse mehr erforderlich ist, muss die Instrumentation Instanz nicht mehr über InstrumentationTestCase#getInstrumentation() werden. Der neue Testläufer verwaltet sie stattdessen über InstrumentationRegistry wo das vom Instrumentation Framework erstellte Kontext- und Umgebungssetup gespeichert wird.

Um auf die Instanz der Instrumentation Klasse zuzugreifen, rufen Sie einfach die statische Methode getInstrumentation() für die InstrumentationRegistry Klasse auf:

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

Lokal erstellen und testen

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

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