Eine inaktive Ressource stellt einen asynchronen Vorgang dar, dessen Ergebnisse sich auf nachfolgende Vorgänge in einem UI-Test. Inaktive Ressourcen werden mit Espresso können Sie diese asynchronen Vorgänge zuverlässiger validieren, wenn Ihre App testen.
Ermitteln, wann inaktive Ressourcen benötigt werden
Espresso bietet ein ausgeklügeltes Angebot an
Synchronisierungsfunktionen. Dieses
charakteristisch des Frameworks, gilt jedoch nur für Vorgänge, die
Nachrichten im MessageQueue
, z. B. eine abgeleitete Klasse von
View
, das seinen Inhalt auf den Bildschirm zeichnet.
Da Espresso keine anderen asynchronen Vorgänge einschließlich die in einem Hintergrundthread ausgeführt werden, kann Espresso in diesen Fällen zu garantieren. Um Espresso auf die Probleme Ihrer App aufmerksam zu machen, lang andauernde Vorgänge ausführen, müssen Sie jeden einzelnen als inaktive Ressource registrieren.
Wenn Sie beim Testen der Ergebnisse der asynchrone Arbeit verwenden, müssen Sie möglicherweise eines der schlechte Behelfslösungen anwenden, um Ihre Tests zu verbessern Zuverlässigkeit:
Thread.sleep()
-Aufrufe werden hinzugefügt. Wenn Sie Künstliche Verzögerungen bei Ihren Tests hinzufügen, dauert es länger, die Ausführung abgeschlossen haben, und Ihre Tests schlagen möglicherweise trotzdem manchmal fehl, wenn sie langsameren Geräten. Außerdem werden diese Verzögerungen nicht gut skaliert, da Ihre App in einer zukünftigen Version zeitaufwendiger asynchron arbeiten müssen.- Wiederholungs-Wrapper implementieren, die mithilfe einer Schleife wiederholt prüfen, Ihre Anwendung noch asynchron arbeitet, bis eine Zeitüberschreitung auftritt. Selbst wenn Sie eine maximale Anzahl von Wiederholungsversuchen in Ihren Tests angeben, verbraucht jede erneute Ausführung Systemressourcen, vor allem die CPU.
- Mit Instanzen von
CountDownLatch
,die zulassen, dass ein oder mehrere Threads warten, bis eine bestimmte Anzahl von Vorgängen die in einem anderen Thread ausgeführt wurden. Für diese Objekte müssen Sie ein Timeout-Länge Andernfalls wird deine App möglicherweise für unbestimmte Zeit blockiert. Die Verschlüsse erhöhen außerdem die Komplexität Ihres Codes, was die Wartung erschwert.
Mit Espresso können Sie diese unzuverlässigen Problemumgehungen aus Ihren Tests entfernen und stattdessen die asynchrone Arbeit Ihrer Anwendung als inaktive Ressourcen.
Gängige Anwendungsfälle
Wenn Sie Vorgänge, die den folgenden Beispielen in Ihren Tests ähneln, Ziehen Sie die Verwendung einer inaktiven Ressource in Betracht:
- Laden von Daten aus dem Internet oder einer lokalen Datenquelle
- Herstellen von Verbindungen zu Datenbanken und Callbacks
- Dienste verwalten, entweder mithilfe eines Systemdienstes oder einer Instanz von
IntentService
- Ausführung komplexer Geschäftslogik, z. B. Bitmaptransformationen.
Es ist besonders wichtig, inaktive Ressourcen zu registrieren, wenn diese Vorgänge eine UI aktualisieren, die Ihre Tests anschließend validieren.
Beispiele für Implementierungen inaktiver Ressourcen
In der folgenden Liste werden mehrere Implementierungsbeispiele für inaktive Ressourcen beschrieben. die Sie in Ihre App integrieren können:
CountingIdlingResource
- Verwaltet einen Zähler der aktiven Aufgaben. Wenn der Zähler null ist,
wird als inaktiv angesehen. Diese Funktion ähnelt stark der eines
Semaphore
In den meisten Fällen ist diese Implementierung Das ist ausreichend, um die asynchrone Arbeit der App während des Tests zu verwalten. UriIdlingResource
- Ähnlich wie
CountingIdlingResource
, aber der Zähler muss für einen bestimmten Zeitraum Null sein, bevor wird als inaktiv angesehen. Diese zusätzliche Wartezeit dauert aufeinanderfolgende Netzwerkanfragen berücksichtigt, bei denen eine App in Ihrem Thread möglicherweise unmittelbar nachdem wir eine Antwort auf eine vorherige Anfrage erhalten haben. IdlingThreadPoolExecutor
- Benutzerdefinierte Implementierung von
ThreadPoolExecutor
die die Gesamtzahl der laufenden Aufgaben innerhalb des erstellten Threads verfolgt Pools. In dieser Klasse wird einCountingIdlingResource
bis den Zähler aktiver Aufgaben verwalten. IdlingScheduledThreadPoolExecutor
- Benutzerdefinierte Implementierung von
ScheduledThreadPoolExecutor
. Es bietet dieselben Funktionalität und FunktionalitätIdlingThreadPoolExecutor
für den Unterricht, sondern auch für zukünftige Aufgaben regelmäßig ausgeführt werden.
Eigene inaktive Ressource erstellen
Wenn Sie inaktive Ressourcen in den Tests Ihrer App verwenden, müssen Sie möglicherweise oder das Logging von Ressourcen. In diesen Fällen werden die Implementierungen aus dem vorherigen Abschnitt möglicherweise nicht ausreichen. In diesem Fall können Sie eine dieser inaktiven Ressourcenimplementierungen erweitern oder Ihre eigene erstellen.
Wenn Sie Ihre eigene Funktion für inaktive Ressourcen implementieren, sollten Sie Folgendes am besten beibehalten im Hinterkopf, insbesondere an die erste:
- Übergänge in den Inaktivitätszustand außerhalb von Inaktivitätsprüfungen aufrufen.
- Wenn Ihre App inaktiv wird, rufen Sie
onTransitionToIdle()
außerhalb der ImplementierungenisIdleNow()
Auf diese Weise Espresso macht keine zweite, unnötige Prüfung, um zu bestimmen, ob ein bestimmtes inaktive Ressource ist inaktiv.
Das folgende Code-Snippet veranschaulicht diese Empfehlung:
Kotlin
fun isIdle() { // DON'T call callback.onTransitionToIdle() here! } fun backgroundWorkDone() { // Background work finished. callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle. // Don't do any post-processing work beyond this point. Espresso now // considers your app to be idle and moves on to the next test action. }
Java
public void isIdle() { // DON'T call callback.onTransitionToIdle() here! } public void backgroundWorkDone() { // Background work finished. callback.onTransitionToIdle() // Good. Tells Espresso that the app is idle. // Don't do any post-processing work beyond this point. Espresso now // considers your app to be idle and moves on to the next test action. }
- Registrieren Sie inaktive Ressourcen, bevor Sie sie benötigen.
Die Synchronisierungsvorteile von inaktiven Ressourcen werden nur wirksam nach dem ersten Aufruf des Codes dieser Ressource durch Espresso
isIdleNow()
-Methode.Die folgende Liste enthält einige Beispiele für diese Eigenschaft:
- Wenn Sie eine inaktive Ressource in einer Methode registrieren, die mit
@Before
annotiert ist, wird die inaktive Ressource in der ersten Zeile jedes Tests wirksam. - Wenn Sie eine inaktive Ressource in einem Test registrieren, wird bei der nächsten Espresso-basierten Aktion wirksam. Dieses Verhalten tritt auch dann auf, wenn die nächste Aktion im selben Test ist wie die Anweisung, die registriert die inaktive Ressource.
- Wenn Sie eine inaktive Ressource in einer Methode registrieren, die mit
- Registrierung inaktiver Ressourcen aufheben, nachdem Sie sie nicht mehr verwendet haben
Um Systemressourcen zu sparen, sollten Sie inaktive Ressourcen so schnell abmelden da Sie sie nicht mehr benötigen. Wenn Sie beispielsweise eine inaktive Ressource registrieren, in einer Methode, die mit
@Before
annotiert ist, empfiehlt es sich, die Registrierung dieser Ressource in einem die mit@After
annotiert ist.- Verwenden Sie eine inaktive Registry, um inaktive Ressourcen zu registrieren und ihre Registrierung aufzuheben.
Wenn Sie diesen Container für die inaktiven Ressourcen Ihrer App verwenden, können Sie inaktive Ressourcen bei Bedarf wiederholt von der Registrierung abmelden und trotzdem konsistente verhalten.
- Innerhalb inaktiver Ressourcen nur einen einfachen App-Status beibehalten.
Beispielsweise sollten die inaktiven Ressourcen, die Sie implementieren und registrieren, Verweise auf
View
-Objekte enthalten.
Inaktive Ressourcen registrieren
Espresso stellt eine Containerklasse bereit, in die Sie den inaktiveren Status Ihrer Anwendung platzieren können.
Ressourcen. Dieser Kurs namens
IdlingRegistry
, ist ein
eigenständiges Artefakt, das der Anwendung minimalen Aufwand verursacht. Die Klasse
können Sie mit den folgenden Schritten die Leistung Ihrer App
Verwaltbarkeit:
- Erstellen Sie einen Verweis auf die
IdlingRegistry
anstelle der inaktiven Ressourcen die sie in den Tests Ihrer App enthält. - Unterschiede in der Sammlung inaktiver Ressourcen beibehalten, die Sie für für jede Build-Variante.
- Inaktive Ressourcen in den Diensten Ihrer App definieren, nicht in der UI Komponenten, die auf diese Dienste verweisen.
Inaktive Ressourcen in die Anwendung einbinden
Sie können einer App zwar auf unterschiedliche Weise inaktive Ressourcen hinzufügen, Bei diesem Ansatz wird die Kapselung für Ihre App beibehalten, während gleichzeitig können Sie einen bestimmten Vorgang angeben, den eine inaktive Ressource darstellt.
Empfohlene Vorgehensweise
Wenn Sie Ihrer App inaktive Ressourcen hinzufügen, empfehlen wir unbedingt, die inaktive Ressourcenlogik in der App selbst und führt nur die Registrierung und in Ihren Tests durchführen.
Die ungewöhnliche Situation, in der Sie eine reine Testoberfläche Produktionscode können Sie mit diesem Ansatz inaktive Ressourcen den Sie bereits haben, und behalten Sie dabei die APK-Größe und Methodenanzahl Ihrer App bei.
Alternative Ansätze
Wenn Sie in der Produktionsphase Ihrer App keine Logik für inaktive Ressourcen haben möchten gibt es mehrere andere praktikable Integrationsstrategien:
- Build-Varianten wie die von Gradle erstellen Produkt Flavor-Versionen und verwenden Sie inaktive Ressourcen nur im Debug-Build Ihrer App.
- Verwenden Sie ein Abhängigkeitsinjektions-Framework wie Dagger, um den inaktiven Status Ihrer App einzuschleusen Grafik zur Ressourcenabhängigkeit in Ihre Tests einbinden. Wenn Sie Dagger 2 verwenden, Die Injektion selbst sollte aus einer Unterkomponente stammen.
Implementieren Sie eine inaktive Ressource in den Tests Ihrer App und geben Sie den Teil frei App-Implementierung, die in diesen Bereichen synchronisiert werden muss, Tests durchführen.
Achtung : Diese Designentscheidung scheint eine eigenständige Referenz auf inaktive Ressourcen erstellen, Datenkapselung in allen Anwendungen mit Ausnahme der einfachsten.
Weitere Informationen
Weitere Informationen zur Verwendung von Espresso in Android-Tests finden Sie in der in den folgenden Ressourcen.
Produktproben
- IdlingResourceSample: Synchronisierung mit Hintergrundjobs.