Erweiterte Testeinrichtung

Unter In Android Studio testen und Über die Befehlszeile testen wird beschrieben, wie Sie grundlegende Testkonfigurationen einrichten und ausführen. Wenn Ihre App und ihre Testanforderungen jedoch komplexer werden, müssen Sie Ihre Testkonfigurationen möglicherweise weiter anpassen. Eine erweiterte Testeinrichtung ist beispielsweise erforderlich, wenn Sie Folgendes tun möchten:

  • Instrumentierte Tests nur für eine bestimmte Build-Variante ausführen oder die Manifesteinstellungen überschreiben
  • Sie können den Build-Typ ändern, für den Ihre Tests ausgeführt werden, oder die Gradle-Optionen konfigurieren.
  • Lagern Sie Ihre instrumentierten Tests in ein eigenes Testmodul aus.
  • Führen Sie im Rahmen Ihrer Continuous Integration-Einrichtung erweiterte Tests durch.

Auf dieser Seite werden verschiedene Möglichkeiten zum Konfigurieren Ihrer Tests beschrieben, wenn die Standardeinstellungen nicht Ihren Anforderungen entsprechen.

Instrumentierten Test für eine Build-Variante erstellen

Wenn Ihr Projekt Build-Varianten mit eindeutigen Quellsätzen enthält, sollten Sie instrumentierte Tests einbeziehen, die diesen Quellsätzen entsprechen. So bleibt Ihr Testcode übersichtlich und Sie können nur die Tests ausführen, die für eine bestimmte Build-Variante gelten.

Wenn Sie Instrumentierungstests mit einer Build-Variante verknüpfen möchten, platzieren Sie sie in einem eigenen Source-Set unter src/androidTestVariantName.

Instrumentierte Tests im src/androidTest/-Source-Set werden von allen Build-Varianten gemeinsam verwendet. Wenn Sie ein Test-APK für die Variante „MyFlavor“ Ihrer App erstellen, kombiniert Gradle die Quellsätze src/androidTest/ und src/androidTestMyFlavor/.

So fügen Sie Ihrer Build-Variante in Android Studio ein Test-Source-Set hinzu:

  1. Klicken Sie im Fenster Projekt auf das Menü und wählen Sie die Ansicht Projekt aus.
  2. Klicken Sie im entsprechenden Modulordner mit der rechten Maustaste auf den Ordner src und dann auf Neu > Verzeichnis.
  3. Geben Sie als Verzeichnisnamen „androidTestVariantName“ ein. Wenn Sie beispielsweise eine Build-Variante mit dem Namen „MyFlavor“ haben, verwenden Sie den Verzeichnisnamen androidTestMyFlavor.
  4. Klicken Sie auf OK.
  5. Klicken Sie mit der rechten Maustaste auf das neue Verzeichnis und wählen Sie Neu > Verzeichnis aus.
  6. Geben Sie „java“ als Verzeichnisnamen ein und klicken Sie auf OK.

Jetzt können Sie diesem neuen Source-Set Tests hinzufügen. Folgen Sie dazu dieser Anleitung. Wenn Sie das Dialogfeld Zielverzeichnis auswählen erreichen, wählen Sie das neue Varianten-Source-Set aus.

In der folgenden Tabelle sehen Sie ein Beispiel dafür, wie sich Instrumentierungstestdateien in Quellsets befinden können, die den Code-Quellsets der App entsprechen:

Tabelle 1. App-Quellcode und entsprechende Instrumentierungstestdateien

Pfad zur App-Klasse Pfad zur entsprechenden Instrumentierungstestklasse
src/main/kotlin+java/Example.kt src/androidTest/java/AndroidExampleTest.kt
src/myFlavor/kotlin+java/Example.kt src/androidTestMyFlavor/java/AndroidExampleTest.kt

Wie bei den Quellsätzen Ihrer App werden beim Gradle-Build Dateien aus verschiedenen Testquellsätzen zusammengeführt und überschrieben. In diesem Fall wird die Datei AndroidExampleTest.kt im Source-Set androidTestMyFlavor durch die Version im Source-Set androidTest überschrieben. Das liegt daran, dass die Produktvarianten-Quellgruppe Vorrang vor der Hauptquellgruppe hat.

Wenn Sie im Selektor für Build-Varianten verschiedene Produktvarianten auswählen, werden in der Ansicht Android die entsprechenden androidTest-Ordner angezeigt, um die verwendeten Ordner zu sehen:

Die MyFlavor-Variante ist ausgewählt und der Ordner „androidTestMyFlavor“ wird in der Android-Ansicht angezeigt.
Abbildung 1: Die MyFlavor-Variante ist ausgewählt. Der Ordner androidTestMyFlavor wird in der Android-Ansicht angezeigt.

Der Ordner androidTestMyFlavor wird nicht angezeigt, wenn eine andere Variante ausgewählt ist:

Die Variante „OtherFlavor“ ist ausgewählt und der Ordner „androidTestMyFlavor“ wird in der Android-Ansicht nicht angezeigt.
Abbildung 2. Die Variante OtherFlavor ist ausgewählt. Der Ordner androidTestMyFlavor wird in der Android-Ansicht nicht angezeigt.

Wenn Sie die Ansicht Projekt verwenden, sieht das Ganze etwas anders aus, aber das Prinzip ist dasselbe:

Die Variante „MyFlavor“ ist ausgewählt und der Ordner „androidTestMyFlavor“ ist in der Projektansicht aktiv.
Abbildung 3: Die MyFlavor-Variante ist ausgewählt und der Ordner androidTestMyFlavor ist in der Ansicht Projekt aktiv.

Wenn eine andere Variante ausgewählt ist, ist der Ordner androidTestMyFlavor weiterhin sichtbar, wird aber nicht als aktiv angezeigt:

Die Variante „OtherFlavor“ ist ausgewählt und der Ordner „androidTestMyFlavor“ ist in der Projektansicht nicht aktiv.
Abbildung 4: Die Variante OtherFlavor ist ausgewählt. Der Ordner androidTestMyFlavor ist in der Ansicht Projekt nicht aktiv.

Weitere Informationen zum Zusammenführen von Quellsätzen finden Sie unter Quellsätze.

Manifesteinstellungen für die Instrumentierung konfigurieren

Instrumentierte Tests werden in ein separates APK mit einer eigenen AndroidManifest.xml-Datei eingebunden. Wenn Gradle Ihr Test-APK erstellt, wird die Datei AndroidManifest.xml automatisch generiert und mit dem Knoten <instrumentation> konfiguriert. Gradle konfiguriert diesen Knoten unter anderem, um sicherzustellen, dass mit der Eigenschaft targetPackage der richtige Paketname der zu testenden App angegeben wird.

Wenn Sie andere Einstellungen für diesen Knoten ändern möchten, erstellen Sie entweder eine weitere Manifestdatei im Test-Source-Set oder konfigurieren Sie die Datei build.gradle auf Modulebene, wie im folgenden Codebeispiel gezeigt. Eine vollständige Liste der Optionen finden Sie in der BaseFlavor API-Referenz.

Kotlin

android {
    ...
    defaultConfig {
        ...
        testApplicationId = "com.example.test"
        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
        testHandleProfiling = true
        testFunctionalTest = true
    }
}

Groovy

android {
    ...
    defaultConfig {
        ...
        testApplicationId "com.example.test"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        testHandleProfiling true
        testFunctionalTest true
    }
}

Mit jeder konfigurierten Produktvariante können Sie Attribute im defaultConfig {}-Block überschreiben. Weitere Informationen finden Sie unter Produktvarianten konfigurieren.

Die Eigenschaften im Snippet sind:

Einstellung Beschreibung
testApplicationId Gibt die Anwendungs-ID für das Test-APK an.
testInstrumentationRunner Gibt den vollständig qualifizierten Klassennamen des Testinstrumentierungs-Runners an.
testHandleProfiling Wenn auf true festgelegt, kann die Instrumentierungsklasse das Profiling starten und beenden.
Wenn false festgelegt ist, erfolgt die Profilerstellung während der gesamten Ausführungszeit der Instrumentierungsklasse.
testFunctionalTest Wenn der Wert auf true gesetzt ist, gibt er an, dass das Android-System die Instrumentierungsklasse als Funktionstest ausführen soll.
Der Standardwert ist false.

Test-Build-Typ ändern

Standardmäßig werden alle Instrumentierungstests für den Build-Typ debug ausgeführt. Sie können dies in Ihrer build.gradle-Datei auf Modulebene mit der Eigenschaft testBuildType in einen anderen Build-Typ ändern. Wenn Sie Ihre Tests beispielsweise für den Build-Typ staging ausführen möchten, bearbeiten Sie die Datei wie im folgenden Snippet gezeigt:

Kotlin

android {
    ...
    testBuildType = "staging"
}

Groovy

android {
    ...
    testBuildType "staging"
}

Gradle-Testoptionen konfigurieren

Mit dem Android Gradle-Plug-in können Sie bestimmte Optionen für alle oder nur einige Ihrer Tests angeben. Verwenden Sie in der Datei build.gradle auf Modulebene den Block testOptions, um Optionen anzugeben, die ändern, wie Gradle alle Ihre Tests ausführt:

Kotlin

android {
    ...
    // Encapsulates options for running tests.
    testOptions {
        reportDir = "$rootDir/test-reports"
        resultsDir = "$rootDir/test-results"
    }
}

Groovy

android {
    ...
    // Encapsulates options for running tests.
    testOptions {
        reportDir "$rootDir/test-reports"
        resultsDir "$rootDir/test-results"
    }
}

Mit dem Attribut reportDir wird das Verzeichnis geändert, in dem Gradle Testberichte speichert. Standardmäßig speichert Gradle Testberichte im Verzeichnis path_to_your_project/module_name /build/outputs/reports/. $rootDir legt den Pfad relativ zum Stammverzeichnis des aktuellen Projekts fest.

Mit der Property resultsDir wird das Verzeichnis geändert, in dem Gradle Testergebnisse speichert. Standardmäßig speichert Gradle Testergebnisse im Verzeichnis path_to_your_project/module_name /build/outputs/test-results/. $rootDir legt den Pfad relativ zum Stammverzeichnis des aktuellen Projekts fest.

Wenn Sie Optionen nur für lokale Einheitentests angeben möchten, konfigurieren Sie den Block unitTests in testOptions.

Kotlin

android {
    ...
    testOptions {
        ...
        // Encapsulates options for local unit tests.
        unitTests {
            returnDefaultValues = true

            all {
                jvmArgs = listOf("-XX:MaxPermSize=256m")

                 if (it.name == "testDebugUnitTest") {
                    systemProperty = mapOf("debug" to "true")
                }
                ...
            }
        }
    }
}

Groovy

android {
    ...
    testOptions {
        ...
        // Encapsulates options for local unit tests.
        unitTests {
            returnDefaultValues true

            all {
                jvmArgs '-XX:MaxPermSize=256m'

                if (it.name == 'testDebugUnitTest') {
                    systemProperty 'debug', 'true'
                }
                ...
            }
        }
    }
}

Standardmäßig wird bei lokalen Unittests eine Ausnahme ausgelöst, wenn der zu testende Code versucht, auf Android-Plattform-APIs zuzugreifen, es sei denn, Sie simulieren Android-Abhängigkeiten selbst oder mit einem Testframework wie Mockito. Sie können jedoch das Attribut returnDefaultValues aktivieren, damit beim Zugriff auf Plattform-APIs entweder „null“ oder „0“ zurückgegeben wird, anstatt eine Ausnahme auszulösen.

Der Block all enthält Optionen zum Steuern der Ausführung lokaler Unittests durch Gradle. Eine Liste aller Optionen, die Sie angeben können, finden Sie in der Gradle-Referenzdokumentation.

Mit der Eigenschaft jvmArgs werden JVM-Argumente für die Test-JVM(s) festgelegt.

Sie können auch den Namen der Aufgabe prüfen, um Optionen nur auf die von Ihnen angegebenen Tests anzuwenden. Im Beispiel-Snippet ist die Eigenschaft debug auf true festgelegt, aber nur für die Aufgabe testDebugUnitTest.

Separate Testmodule für instrumentierte Tests verwenden

Wenn Sie ein separates Modul für instrumentierte Tests verwenden möchten, um den Rest Ihres Codes von Ihren Tests zu isolieren, erstellen Sie ein separates Testmodul und konfigurieren Sie seinen Build ähnlich wie den eines Bibliotheksmoduls.

So erstellen Sie ein Testmodul:

  1. Bibliotheksmodul erstellen
  2. Wenden Sie in der Datei build.gradle auf Modulebene das com.android.test-Plugin anstelle von com.android.library an.
  3. Klicken Sie auf Projekt synchronisieren .

Nachdem Sie das Testmodul erstellt haben, können Sie den Testcode in das Haupt- oder Variantensource-Set einfügen (z. B. src/main/kotlin+java oder src/variant/kotlin+java). Wenn in Ihrem App-Modul mehrere Produktvarianten definiert sind, können Sie diese Varianten in Ihrem Testmodul neu erstellen. Mithilfe der variantenbewussten Abhängigkeitsverwaltung versucht das Testmodul, die entsprechende Variante im Zielmodul zu testen.

Standardmäßig enthalten Testmodule nur eine Debug-Variante und testen nur diese. Sie können jedoch neue Build-Typen erstellen, die dem getesteten App-Projekt entsprechen. Wenn das Testmodul einen anderen Build-Typ als den Debug-Typ testen soll, verwenden Sie VariantFilter, um die Debug-Variante im Testprojekt zu deaktivieren, wie unten gezeigt:

Kotlin

android {
    variantFilter {
        if (buildType.name == "debug") {
            ignore = true
        }
    }
}

Groovy

android {
    variantFilter { variant ->
        if (variant.buildType.name.equals('debug')) {
            variant.setIgnore(true);
        }
    }
}

Wenn ein Testmodul nur auf bestimmte Produktvarianten oder Build-Typen einer App ausgerichtet sein soll, können Sie mit der matchingFallbacks-Eigenschaft nur die Varianten testen, die Sie testen möchten. Dadurch muss das Testmodul diese Varianten nicht selbst konfigurieren.