2015-02-08 19 views
48

Czy ktoś wie, jak przetestować wygląd wiadomości Toast w Androidzie? W robotium jego łatwe & użyłem, ale zacząłem pracować w espresso, ale nie otrzymałem dokładnego polecenia.Sprawdzanie wiadomości toastowej w android espresso

+0

którykolwiek z następujących rozwiązanie nie zadziała, jeżeli działalność jest wykończone w w tym samym czasie, w którym wyświetlany jest toast. – Slav

Odpowiedz

80

To nieco długa wypowiedź działa dla mnie:

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())); 
+0

Próbowałem już i pracowałem dla mnie. Dzięki –

+4

'is()' metoda jest zbędna – Slava

+3

@Slava jest poprawna, można to zrobić poprzez usunięcie: onView (withText (R.string.TOAST_STRING)). InRoot (withDecorView (not (getActivity(). GetWindow(). getDecorView()))) .check (mecze (isDisplayed())); – bond

-3

Sposób zaimplementowania tostów umożliwia wykrycie toastu. Nie ma jednak sposobu sprawdzenia, czy zażądano tosty, przez wywołanie show()) lub zablokowania czasu między show() i kiedy toast stał się widoczny. To otwiera nierozwiązywalne problemy z synchronizacją czasu (że możesz tylko adresować przez sen & nadzieję).

Jeśli naprawdę naprawdę chcesz to sprawdzić, tu jest nie tak całkiem alternatywa korzystania Mockito i szpiega badawczej:

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(); 
+9

Md Hussain, czy nie chcesz dodać linku w swojej odpowiedzi do miejsca, w którym je skopiowałeś - https://groups.google.com/forum/#!searchin/android-test-kit-discuss/toast/ android-test-kit-discuss/uaHdXuVm-Bw/EBIGyA0Omj0J? – denys

+3

Chociaż prawdą jest, że odpowiedź została skopiowana, podnosi ona dobry punkt. Przyjęta odpowiedź zapewnia test nie-hermetyczny, ponieważ wpływa na potencjalne następne wykonanie. – mdelolmo

30

Przyjęta odpowiedź jest dobra, ale dla mnie nie działa. Więc szukałem trochę i znalazłem this blog article. To dało mi pojęcie, jak to zrobić i zaktualizowałem powyższe rozwiązanie.

Najpierw wdrożony 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; 
    } 

} 

Potem realizowane moje metody wyboru tak:

public void isToastMessageDisplayed(int textId) { 
    onView(withText(textId)).inRoot(MobileViewMatchers.isToast()).check(matches(isDisplayed())); 
} 

MobileViewMatchers jest kontenerem dla dostępu do dopasowujących. Tam zdefiniowałem metodę statyczną isToast().

public static Matcher<Root> isToast() { 
    return new ToastMatcher(); 
} 

To działa jak urok dla mnie.

+0

To nie działa dla mnie, ponieważ test ciągle pętli. Jedyną rzeczą, która działa, jest to, że gdy dotknę ekranu, gdy toast jest otwarty, wydaje się, że przestaje działać na biegu jałowym, a następnie zadziała. Jakieś pomysły? – AdamMc331

+0

Muszę znać twoją konfigurację testu. Co chcesz przetestować i co jest wyświetlane? Brzmi jak problem z postępem, http://stackoverflow.com/questions/33289152/progressbars-and-espresso/36201647#36201647. Czy dzieje się to we wszystkich wersjach interfejsu API? –

+0

Nie testowałem wielu wersji interfejsu API. To, co się dzieje, to wywołanie API po wczytaniu fragmentu, który kpi z odpowiedzi na niepowodzenie, w którym to przypadku wszystko, co robimy, pokazuje toast. Mogę spróbować zrozumieć to, co robię dzisiaj. – AdamMc331

7

Najpierw upewnij się, aby importować:

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; 

wewnątrz klasy prawdopodobnie masz regułę tak:

@Rule 
public ActivityTestRule<MyNameActivity> activityTestRule = 
      new ActivityTestRule<>(MyNameActivity.class); 

wewnątrz testu:

MyNameActivity activity = activityTestRule.getActivity(); 
onView(withText(R.string.toast_text)). 
    inRoot(withDecorView(not(is(activity.getWindow().getDecorView())))). 
    check(matches(isDisplayed())); 

ten pracował dla mnie i było dość łatwe w użyciu.

1

Najpierw utwórz Matcher cutom Toast które możemy wykorzystać w naszych testach -

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. sprawdzić, czy wiadomość jest wyświetlana Toast

onView(withText(R.string.mssage)).inRoot(new ToastMatcher()) 
.check(matches(isDisplayed())); 

2. Test jeżeli Wiadomość Toast nie jest wyświetlana

onView(withText(R.string.mssage)).inRoot(new ToastMatcher()) 
.check(matches(not(isDisplayed()))); 

3.id Test Toast zawiera szczegółowe wiadomości tekstowej

onView(withText(R.string.mssage)).inRoot(new ToastMatcher()) 
.check(matches(withText("Invalid Name")); 

Dzięki, Anuja

Uwaga - ta odpowiedź jest z This POST.

+0

Powinno być: , jeśli (windowToken == appToken) { // oznacza, że ​​to okno nie jest zawarte w żadnym innym oknie. return true; } –

+0

@ januja jain, gdy http://stackoverflow.com/a/40756080/5230044 odpowiedź działa wtedy, dlaczego powinniśmy odnosić się do twojej odpowiedzi – cammando

+1

jak odnotowano w oryginalnym wpisie w komentarzach, to NIE działa. Nie działa z wyjątkiem.Również ten post nie zawiera zwrotu true; po komentarzu, gdy tokeny pasują, więc to też nie zadziała. – user330844

Powiązane problemy