Würde jemand wissen, wie man das Aussehen einer Toast-Nachricht in android Espresso testen? In Roboter seine einfache & Ich benutzte, aber fing an, in Espresso zu arbeiten, aber nicht den genauen Befehl zu bekommen.Toast-Nachricht in Android-Espresso überprüfen
Antwort
Diese etwas lange Anweisung funktioniert für mich:
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
....
onView(withText(R.string.TOAST_STRING)).inRoot(withDecorView(not(is(getActivity().getWindow().getDecorView())))).check(matches(isDisplayed()));
Ich habe es schon versucht und für mich gearbeitet. Danke –
'is()' Methode ist redundant – Slava
@Slava ist richtig, es kann durch Entfernen gemacht werden: onView (withText (R.string.TOAST_STRING)). InRoot (withDecorView (nicht (getActivity(). GetWindow(). getDecorView()))) .check (entspricht (isDisplayed())); – bond
Die Art und Weise, wie Toasts implementiert werden, ermöglicht es, zu erkennen, dass ein Toast angezeigt wurde. Es gibt jedoch keine Möglichkeit zu sehen, ob ein Toast angefordert wurde, durch einen Aufruf von show()) oder zwischen dem Zeitraum zwischen show() und wann der Toast sichtbar wurde. Dies ist eröffnet unlösbare Timing-Probleme (die Sie nur durch Schlaf & hoffe).
Wenn Sie wirklich, wirklich dies überprüfen wollen, hier ist eine nicht-so-recht Alternative mit Mockito und einen Test spy:
public interface Toaster {
public void showToast(Toast t);
private static class RealToaster {
@Override
public void showToast(Toast t) {
t.show();
}
public static Toaster makeToaster() {
return new RealToaster();
}
}
Then in your test
public void testMyThing() {
Toaster spyToaster = Mockito.spy(Toaster.makeToaster());
getActivity().setToaster(spyToaster);
onView(withId(R.button)).perform(click());
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
// must do this on the main thread because the matcher will be interrogating a view...
Mockito.verify(spyToaster).showToast(allOf(withDuration(Toast.LENGTH_SHORT), withView(withText("hello world"));
});
}
// create a matcher that calls getDuration() on the toast object
Matcher<Toast> withDuration(int)
// create a matcher that calls getView() and applies the given view matcher
Matcher<Toast> withView(Matcher<View> viewMatcher)
another answer regarding this
if(someToast == null)
someToast = Toast.makeText(this, "sdfdsf", Toast.LENGTH_LONG);
boolean isShown = someToast.getView().isShown();
Md Hussain, möchtest du keinen Link in deiner Antwort zu dem Ort hinzufügen, an dem du sie kopiert hast - https://groups.google.com/forum/#!searchin/android-test-kit-discuss/toast/ android-test-kit-diskutieren/uaHdXuVm-Bw/EBIGyA0Omj0J? – denys
Obwohl es stimmt, dass die Antwort kopiert wird, bringt es einen guten Punkt. Die akzeptierte Antwort stellt einen nicht-hermetischen Test bereit, da sie eine mögliche nachfolgende Ausführung beeinflusst. – mdelolmo
Die angenommene Antwort ist eine gute, hat aber nicht für mich funktioniert. Also habe ich ein wenig gesucht und this blog article gefunden. Dies gab mir eine Idee, wie es geht, und ich aktualisierte die obige Lösung.
Zuerst implementiert ich die ToastMatcher:
import android.os.IBinder;
import android.support.test.espresso.Root;
import android.view.WindowManager;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
public class ToastMatcher extends TypeSafeMatcher<Root> {
@Override
public void describeTo(Description description) {
description.appendText("is toast");
}
@Override
public boolean matchesSafely(Root root) {
int type = root.getWindowLayoutParams().get().type;
if (type == WindowManager.LayoutParams.TYPE_TOAST) {
IBinder windowToken = root.getDecorView().getWindowToken();
IBinder appToken = root.getDecorView().getApplicationWindowToken();
if (windowToken == appToken) {
// windowToken == appToken means this window isn't contained by any other windows.
// if it was a window for an activity, it would have TYPE_BASE_APPLICATION.
return true;
}
}
return false;
}
}
Dann implementiert ich meine Prüfmethoden wie folgt aus:
public void isToastMessageDisplayed(int textId) {
onView(withText(textId)).inRoot(MobileViewMatchers.isToast()).check(matches(isDisplayed()));
}
MobileViewMatchers ein Container ist die Matcher für den Zugriff. Dort habe ich die statische Methode isToast()
definiert.
public static Matcher<Root> isToast() {
return new ToastMatcher();
}
Das funktioniert wie ein Zauber für mich.
Dies funktioniert nicht für mich, da der Test kontinuierlich loops. Die einzige Sache, die funktioniert, ist, wenn ich den Bildschirm berühre, während der Toast geöffnet ist, scheint es im Leerlauf zu stoppen und wird dann funktionieren. Irgendwelche Ideen? – AdamMc331
Ich muss Ihre Testkonfiguration kennen. Was möchten Sie testen und was wird angezeigt? Klingt wie ein Fortschritt Problem, http://stackoverflow.com/questions/33289152/progressbars-and-espresso/36201647#36201647. Tritt dies bei allen API-Versionen auf? –
Ich habe nicht mehrere API-Versionen getestet. Was passiert, ist, dass wir einen API-Aufruf machen, wenn ein Fragment geladen wird, was eine Fehlerantwort verspottet. In diesem Fall wird nur der Toast angezeigt. Ich kann versuchen, etwas von dem zu machen, was ich heute mache. – AdamMc331
Stellen Sie zunächst sicher importieren:
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
In Ihrer Klasse haben Sie wahrscheinlich eine Regel wie folgt aus:
@Rule
public ActivityTestRule<MyNameActivity> activityTestRule =
new ActivityTestRule<>(MyNameActivity.class);
In Ihrem Test:
MyNameActivity activity = activityTestRule.getActivity();
onView(withText(R.string.toast_text)).
inRoot(withDecorView(not(is(activity.getWindow().getDecorView())))).
check(matches(isDisplayed()));
Das ist für mich gearbeitet und es war ziemlich einfach zu bedienen.
zuerst eine cutom Toast Matcher schaffen, die wir in unserem Testfälle können -
public class ToastMatcher extends TypeSafeMatcher<Root> {
@Override public void describeTo(Description description) {
description.appendText("is toast");
}
@Override public boolean matchesSafely(Root root) {
int type = root.getWindowLayoutParams().get().type;
if ((type == WindowManager.LayoutParams.TYPE_TOAST)) {
IBinder windowToken = root.getDecorView().getWindowToken();
IBinder appToken = root.getDecorView().getApplicationWindowToken();
if (windowToken == appToken) {
//means this window isn't contained by any other windows.
}
}
return false;
}
1. Prüfe, ob die Toast Nachricht angezeigt wird
onView(withText(R.string.mssage)).inRoot(new ToastMatcher())
.check(matches(isDisplayed()));
2. Testen Sie, ob die Toast-Nachricht wird nicht angezeigt
onView(withText(R.string.mssage)).inRoot(new ToastMatcher())
.check(matches(not(isDisplayed())));
3.Test-ID der Toast enthält spezifische Textnachricht
onView(withText(R.string.mssage)).inRoot(new ToastMatcher())
.check(matches(withText("Invalid Name"));
Danke, Anuja
Hinweis - diese Antwort von This POST.
Es sollte sein: if (windowToken == appToken) { // bedeutet, dass dieses Fenster nicht von anderen Fenstern enthalten ist. Rückkehr wahr; } –
@anuja jain wenn http://stackoverflow.com/a/40756080/5230044 Antwort funktioniert dann warum sollten wir beziehen uns auf Ihre Antwort – cammando
wie im ursprünglichen Beitrag in den Kommentaren erwähnt, das funktioniert nicht. Es schlägt mit einer Ausnahme fehl.Auch in diesem Beitrag fehlt die Rückkehr wahr; nach dem Kommentar, wenn die Token übereinstimmen, wird es auch nicht funktionieren. – user330844
Jede der folgenden Lösung funktioniert nicht, wenn die Aktivität bei beendet wird die gleiche Zeit wie der Toast angezeigt wird. – Slav