Espresso behauptet, dass es keine Notwendigkeit gibt Thread.sleep();
, aber mein Code funktioniert nur, wenn ich ihn einbinde. Ich verbinde mich mit einer IP. Während der Verbindung wird ein Fortschrittsdialog angezeigt. Ich muss sleep
warten, bis der Dialog beendet ist. Dies ist mein Testausschnitt, in dem ich ihn verwende:
IP.enterIP(); // fills out an IP dialog (this is done with espresso)
//progress dialog is now shown
Thread.sleep(1500);
onView(withId(R.id.button).perform(click());
Ich habe diesen Code versucht , mit und ohne das , Thread.sleep();
aber es sagt R.id.Button
nicht existiert. Ich kann es nur mit Schlaf zum Laufen bringen.
Außerdem habe ich versucht, Thread.sleep();
durch Dinge wie getInstrumentation().waitForIdleSync();
und immer noch kein Glück zu ersetzen .
Ist dies der einzige Weg, dies zu tun? Oder fehlt mir etwas?
Danke im Voraus.
android
testing
android-espresso
Chad Bingham
quelle
quelle
Antworten:
In meinen Augen wird der richtige Ansatz sein:
Und dann wird das Verwendungsmuster sein:
quelle
Vielen Dank an AlexK für seine großartige Antwort. Es gibt Fälle, in denen Sie den Code etwas verzögern müssen. Es wartet nicht unbedingt auf die Antwort des Servers, sondern wartet möglicherweise darauf, dass die Animation ausgeführt wird. Ich persönlich habe ein Problem mit Espresso idolingResources (ich glaube, wir schreiben viele Codezeilen für eine einfache Sache), also habe ich die Art und Weise, wie AlexK es tat, in folgenden Code geändert:
Sie können also eine
Delay
Klasse erstellen und diese Methode einfügen, um leicht darauf zugreifen zu können. Sie können es in Ihrer Testklasse auf folgende Weise verwenden:onView(isRoot()).perform(waitFor(5000));
quelle
Thread.sleep()
Ich bin auf diesen Thread gestoßen, als ich nach einer Antwort auf ein ähnliches Problem gesucht habe, bei dem ich auf eine Serverantwort gewartet und die Sichtbarkeit von Elementen basierend auf der Antwort geändert habe.
Während die obige Lösung definitiv half, fand ich schließlich dieses hervorragende Beispiel von Chiuki und verwende diesen Ansatz jetzt als meine , wenn ich darauf warte, dass Aktionen während der Leerlaufzeiten der App ausgeführt werden.
Ich habe ElapsedTimeIdlingResource () zu meiner eigenen Utilities-Klasse hinzugefügt , kann dies jetzt effektiv als Espresso-geeignete Alternative verwenden, und jetzt ist die Verwendung nett und sauber:
quelle
I/TestRunner: java.lang.NoClassDefFoundError: fr.x.app.y.testtools.ElapsedTimeIdlingResource
Fehlermeldung. Irgendeine Idee. Ich benutze Proguard, aber mit deaktivierter Verschleierung.-keep
Anweisung für Klassen hinzu, die nicht gefunden werden, um sicherzustellen, dass ProGuard sie nicht als unnötig entfernt. Weitere Infos hier: developer.android.com/tools/help/proguard.html#keep-codeIch denke, es ist einfacher, diese Zeile hinzuzufügen:
Wartet eine bestimmte Anzahl von Millisekunden (von uptimeMillis), bevor Sie zurückkehren. Ähnlich wie im Schlaf (lang), löst jedoch keine InterruptedException aus. Interrupt () -Ereignisse werden bis zur nächsten unterbrechbaren Operation zurückgestellt. Wird erst zurückgegeben, wenn mindestens die angegebene Anzahl von Millisekunden verstrichen ist.
quelle
Sie können einfach Barista-Methoden verwenden:
BaristaSleepActions.sleep(2000);
BaristaSleepActions.sleep(2, SECONDS);
Barista ist eine Bibliothek, die Espresso verpackt, um zu vermeiden, dass der gesamte Code hinzugefügt wird, der für die akzeptierte Antwort erforderlich ist. Und hier ist ein Link! https://github.com/SchibstedSpain/Barista
quelle
Thread.sleep()
. Es tut uns leid! Es war in einigen der ersten Videos, die Google über Espresso gemacht hat, aber ich weiß nicht mehr, welches ... es war vor einigen Jahren. Es tut uns leid! :·) Oh! Bearbeiten! Ich habe den Link zu dem Video in die PR eingefügt, die ich vor drei Jahren eröffnet habe. Hör zu! github.com/AdevintaSpain/Barista/pull/19Dies ähnelt dieser Antwort , verwendet jedoch anstelle von Versuchen eine Zeitüberschreitung und kann mit anderen ViewInteractions verkettet werden:
Verwendung:
quelle
Ich bin neu in Codierung und Espresso. Obwohl ich weiß, dass die gute und vernünftige Lösung darin besteht, Leerlauf zu verwenden, bin ich noch nicht intelligent genug, um dies zu tun.
Bis ich mich besser auskenne, müssen meine Tests trotzdem irgendwie ausgeführt werden. Daher verwende ich im Moment diese schmutzige Lösung, die eine Reihe von Versuchen unternimmt, ein Element zu finden, stoppt, wenn es es findet, und wenn nicht, schläft es kurz und startet erneut, bis die maximale Anzahl von Versuchen erreicht ist (die höchste Anzahl von Versuchen lag bisher bei etwa 150).
Ich verwende dies in allen Methoden, die Elemente nach ID, Text, übergeordnetem Element usw. finden:
quelle
findById(int itemId)
Methode ein Element zurück (das NULL sein kann), unabhängig davon, ob eswaitForElementUntilDisplayed(element);
true oder false zurückgibt. Das ist also nicht inIdlingResource
s sind mir aufgrund der Granularität der 5-Sekunden-Abfragerate nicht genug (viel zu groß für meinen Anwendungsfall). Die akzeptierte Antwort funktioniert auch bei mir nicht (Erklärung, warum sie bereits im langen Kommentar-Feed dieser Antwort enthalten ist). Danke dafür! Ich habe Ihre Idee aufgegriffen und meine eigene Lösung gefunden, die wie ein Zauber wirkt.Espresso wurde entwickelt, um sleep () -Aufrufe in den Tests zu vermeiden. Ihr Test sollte kein Dialogfeld zur Eingabe einer IP öffnen. Dies sollte die Verantwortung der getesteten Aktivität sein.
Auf der anderen Seite sollte Ihr UI-Test:
Der Test sollte ungefähr so aussehen:
Espresso wartet, bis alles, was sowohl im UI-Thread als auch im AsyncTask-Pool passiert, abgeschlossen ist, bevor Sie Ihre Tests ausführen.
Denken Sie daran, dass Ihre Tests nichts tun sollten, was Ihrer Anwendungsverantwortung entspricht. Es sollte sich wie ein "gut informierter Benutzer" verhalten: Ein Benutzer, der klickt, überprüft, ob etwas auf dem Bildschirm angezeigt wird, aber tatsächlich die IDs der Komponenten kennt
quelle
Sie sollten Espresso Idling Resource verwenden, dies wird in diesem CodeLab empfohlen
Beispiel eines asynchronen Aufrufs vom Presenter
Abhängigkeiten
Für AndroidX
Offizielles Repo: https://github.com/googlecodelabs/android-testing
IdlingResource-Beispiel: https://github.com/googlesamples/android-testing/tree/master/ui/espresso/IdlingResourceSample
quelle
Obwohl ich denke, dass es am besten ist, dafür Leerlaufressourcen zu verwenden ( https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/ ), könnten Sie dies wahrscheinlich als Fallback verwenden:
und nennen Sie es dann in Ihrem Code wie zB:
anstatt
Auf diese Weise können Sie auch Zeitüberschreitungen für Ansichtsaktionen und Ansichtszusicherungen hinzufügen.
quelle
return new TimedViewInteraction(Espresso.onView(viewMatcher));
mitreturn new TimedViewInteraction(Espresso.onView(viewMatcher).check(matches(isDisplayed())));
Mein Dienstprogramm wiederholt die Ausführung von ausführbaren oder aufrufbaren Objekten, bis es nach einer Zeitüberschreitung fehlerfrei oder auslösbar ist. Es funktioniert perfekt für Espresso-Tests!
Angenommen, die letzte Ansichtsinteraktion (Tastenklick) aktiviert einige Hintergrundthreads (Netzwerk, Datenbank usw.). Als Ergebnis sollte ein neuer Bildschirm angezeigt werden, den wir in unserem nächsten Schritt überprüfen möchten. Wir wissen jedoch nicht, wann der neue Bildschirm zum Testen bereit ist.
Der empfohlene Ansatz besteht darin, Ihre App zu zwingen, Nachrichten über Thread-Status an Ihren Test zu senden. Manchmal können wir eingebaute Mechanismen wie OkHttp3IdlingResource verwenden. In anderen Fällen sollten Sie Codeteile an verschiedenen Stellen Ihrer App-Quellen einfügen (Sie sollten die App-Logik kennen!), Nur um die Unterstützung zu testen. Außerdem sollten wir alle Ihre Animationen deaktivieren (obwohl dies Teil der Benutzeroberfläche ist).
Der andere Ansatz wartet, z. B. SystemClock.sleep (10000). Aber wir wissen nicht, wie lange wir warten sollen, und selbst lange Verzögerungen können keinen Erfolg garantieren. Auf der anderen Seite wird Ihr Test lange dauern.
Mein Ansatz ist es, eine Zeitbedingung hinzuzufügen, um die Interaktion anzuzeigen. Zum Beispiel testen wir, dass während 10000 mc (Timeout) ein neuer Bildschirm angezeigt werden soll. Aber wir warten nicht und überprüfen es so schnell wir wollen (z. B. alle 100 ms). Natürlich blockieren wir den Test-Thread so, aber normalerweise ist es genau das, was wir in solchen Fällen brauchen.
Dies ist meine Klassenquelle:
https://gist.github.com/alexshr/ca90212e49e74eb201fbc976255b47e0
quelle
Dies ist ein Helfer, den ich in Kotlin für Android-Tests verwende. In meinem Fall verwende ich longOperation, um die Serverantwort nachzuahmen, aber Sie können sie an Ihren Zweck anpassen.
quelle
Ich werde meine Art, dies zu tun, der Mischung hinzufügen:
So genannt:
Sie können der Funktion suspendUntilSuccess Parameter wie maximale Iterationen, Iterationslänge usw. hinzufügen.
Ich bevorzuge immer noch die Verwendung von Ressourcen im Leerlauf, aber wenn die Tests beispielsweise aufgrund langsamer Animationen auf dem Gerät ausgeführt werden, verwende ich diese Funktion und sie funktioniert gut. Es kann natürlich bis zu 5 Sekunden lang hängen bleiben, bevor es fehlschlägt. Daher kann es die Ausführungszeit Ihrer Tests verlängern, wenn die erfolgreiche Aktion niemals erfolgreich ist.
quelle