android / android-test

An extensive framework for testing Android apps
https://android.github.io/android-test
Apache License 2.0
1.15k stars 309 forks source link

Toast message assertions not working with android 11 and target sdk 30 #803

Open MarieT2020 opened 3 years ago

MarieT2020 commented 3 years ago

Description

On the app I am testing there are a number of toast messages that I check to make sure toasts are displayed with correct text. My espresso tests started to fail when using Android 11 and SDK30.

Steps to Reproduce

I have a simple check where I try to check the text appears on screen for a toast. onView(withText(R.string.toast_text)).inRoot( withDecorView(not(activityRule.activity.window.decorView))) .check(matches(isDisplayed()))

I have also tried with a Custom toast matcher without any luck

fun onToast(
        text: Int,
       @IntRange(from = 1) maximumRetries: Int = MAX_RETRIES
 ): ViewInteraction = onView(withText(text)).inRoot(ToastMatcher(maximumRetries))

class ToastMatcher(private val maximumRetries: Int) : TypeSafeMatcher<Root>() {

private var currentFailures: Int = 0

override fun describeTo(description: Description?) {
    description?.appendText("no toast found after")
}

override fun matchesSafely(item: Root?): Boolean {
    val type: Int? = item?.windowLayoutParams?.get()?.type

    if(TYPE_TOAST == type || TYPE_APPLICATION_OVERLAY == type) {
        val windowToken = item.decorView.windowToken
        val appToken = item.decorView.applicationWindowToken

        if(windowToken == appToken) {
            return true
        }
    }

    return ++currentFailures >= maximumRetries
}
}

onToast(R.string.toast_text) .check(matches(isDisplayed()))

Expected Results

Tests pass. This works as expected when using OS lower than android 11. It also works as expected when using android 11 and sdk 29. I also tried updating the version of androidx and espresso to the latest version 3.3.0 and 1.3.0 but this did not make any difference.

Actual Results

Result when using withDecorView androidx.test.espresso.NoMatchingRootException: Matcher 'with decor view not <DecorView@5ae48a6[TestActivity]>' did not match any of the following roots: [Root{application-window-token=android.view.ViewRootImpl$W@1337585, window-token=android.view.ViewRootImpl$W@1337585, has-window-focus=true, layout-params-type=1, layout-params-string={(0,0)(fillxfill) sim={state=hidden} ty=BASE_APPLICATION wanim=0x10302fe fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND FIT_INSETS_CONTROLLED fitSides=}, decor-view-string=DecorView{id=-1, visibility=VISIBLE, width=1080, height=2160, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(0,0)(fillxfill) sim={state=hidden} ty=BASE_APPLICATION wanim=0x10302fe fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND FIT_INSETS_CONTROLLED fitSides=}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3}}] at dalvik.system.VMStack.getThreadStackTrace(Native Method) at java.lang.Thread.getStackTrace(Thread.java:1736) at androidx.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:96) at androidx.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:59) at androidx.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:322) at androidx.test.espresso.ViewInteraction.check(ViewInteraction.java:306)

Result when using ToastMatcher androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with string from resource id: <2131755255>[toast_text] value: Toast Text. If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:com.squareup.timessquare.CalendarPickerView{1af12d7 VFED.VC.. ........ 0,0-1080,1657 #7f09010e app:id/calendarPv} View Hierarchy: +>DecorView{id=-1, visibility=VISIBLE, width=1080, height=2160, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, layout-params={(0,0)(fillxfill) ty=BASE_APPLICATION wanim=0x10302fe fl=LAYOUT_IN_SCREEN LAYOUT_INSET_DECOR SPLIT_TOUCH HARDWARE_ACCELERATED DRAWS_SYSTEM_BAR_BACKGROUNDS pfl=FORCE_DRAW_STATUS_BAR_BACKGROUND FIT_INSETS_CONTROLLED fitSides=}, tag=null, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=3} |

AndroidX Test and Android OS Versions

AndroidX Test: 1.2.0 Espresso: 3.2.0 Android OS: Android 11 (API 30)

vfa-tamhh commented 3 years ago

Get the same this issue. If I use target lower api 30, It will work fine. Has Anyone fixed it?

dnhirsh1 commented 3 years ago

any update about that issue?

Tangjiahui26 commented 3 years ago

Any updates on this issue? I am still getting the same errors. Any workarounds? Thanks!

davidmcraejr commented 3 years ago

We are also trying to figure this out if anyone has came up with a solution.

seadowg commented 2 years ago

Also experiencing this. We're most likely going to pull out an interface for showing toasts that can be replaced with a recording fake in tests for assertions, but it'd be good to get guidance around if this is something that Espresso will support again in future.

bacarPereira commented 2 years ago

Get the same this issue. When I run the test using ToastMaster or DecorView the test takes a long time to run no matter if it is API 30 or 29 and in the end it fails.

    @Test
    @UiThreadTest
    fun showToastMessage_message_should_be_displayed() {
        val messageExpected = appContext.getString(R.string.toastMessage)
        appContext.showToastMessage(messageExpected))
        onView(withText(messageExpected)).inRoot(ToastMatcher())
            .check(matches(isDisplayed()))
    }
    @Test
    @UiThreadTest
    fun showToastMessage_message_should_be_displayed() {
        val messageExpected = appContext.getString(R.string.toastMessage)
        appContext.showToastMessage(messageExpected))
        onView(withText(messageExpected))
            .inRoot(withDecorView(not(decorView)))
            .check(matches(isDisplayed()))
    }
rbarbish commented 2 years ago

So after looking at every link and StackOverflow it looks like there is no way to check for a toast if targetSdk is 30 as of May 2022?

davidmcraejr commented 2 years ago

@rbarbish I ended up just adding a version check in the test and only running that test on sdks less than 30, not optimal but until a solution is found its what we can do...

arsalan04ahmad commented 2 years ago

I am also not able to find any solution to this issue. If any solution Found pls share:)

AnandaDwiprayoga commented 2 years ago

I face this issue too, when I run my android test in android 7 it works fine, but when I try in my android 11 it fails

clarabez commented 2 years ago

This is also happening to me, so I resolved it replacing inRoot by this solution with UIAutomator and assertTrue:

import androidx.test.platform.app.InstrumentationRegistry
import junit.framework.Assert.assertTrue
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice

val device: UiDevice
        get() = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

assertTrue(device.hasObject(By.text(toastMessageDuplicated)))
arsalan04ahmad commented 2 years ago

@clarabez Won't the ui automator take time initializing?

TWiStErRob commented 2 years ago

Maybe, but you're not having Toasts in all of your tests hopefully, right? 😅

arsalan04ahmad commented 2 years ago

@TWiStErRob Yes I have used Toast as less as possible because of the testing issue. But there are some cases that can only be verified using toast . I am stuck in that :)

clarabez commented 2 years ago

@clarabez Won't the ui automator take time initializing?

It is not in my case, same execution time.

arsalan04ahmad commented 2 years ago

@clarabez Still my test cases are failing can you pls elaborate

val device: UiDevice
        get() = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

This get() is giving syntax error, can you pls share the complete Toast matcher code . It would be really helpful

clarabez commented 2 years ago

@clarabez Still my test cases are failing can you pls elaborate

val device: UiDevice
        get() = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

This get() is giving syntax error, can you pls share the complete Toast matcher code . It would be really helpful

Sure! The project that I am working with this solution is open in my GitHub here. Feel free to check it! :) Let me know if it works for you.

arsalan04ahmad commented 2 years ago

@clarabez I cannot open your project. Its showing page not found. I assume that its in your android testing repository. Can you pls specify the package and the class to look at.

clarabez commented 2 years ago

@clarabez I cannot open your project. Its showing page not found. I assume that its in your android testing repository. Can you pls specify the package and the class to look at.

Ops, sorry, it was private. Now it is public. Link here.

arsalan04ahmad commented 2 years ago

@clarabez It didn't work for me in Android 12 , the assertion always Fails :\

clarabez commented 2 years ago

@clarabez It didn't work for me in Android 12 , the assertion always Fails :\

oh, sad to hear that! :( let us know if you find any valid solution for Android 12

Venkat-juju commented 2 years ago

@clarabez what you are testing in your project is a Snackbar ... not a toast.. this solution don't work for toast

testfacefanpage commented 1 year ago

Hello everyone, does anyone have updates for this topic ? So until now we can not test Toast is displayed from Android 11 with Espresso ? Please share if you have some updates about that. Thank you all.

testfacefanpage commented 1 year ago

Hi @ralf-at-android

When I write the test to verify Toast is displayed like this:

Espresso.onView(withText("Toast message here")).inRoot(withDecorView(not(decorView))).check(matches(isDisplayed()))

It work fine in Android lower Android 11. But from Android 11 I have an exception like this:

androidx.test.espresso.NoMarchingRootException: Matcher 'with decor view not DecorView@17028cf[MyActivity]' did not match any of the following roots: [Root{application-window-token=android.view.ViewRootImpl$W@3daab3f, window-token=android.view.ViewRootImpl$W@3daab3f, has-window-focus=true, layout-params-type=1, layout-params-string={(0,0)(fillxfill) ty=BASE_APPLICATION wanim=0x10302fe

Thank you for your idea about that!

sarimmehdi commented 1 year ago

So, we are unable to test toasts now? Is there a reason for that? Security issues?

luongvo commented 1 year ago

+1 can't test with a ToastMatcher on API 30 https://stackoverflow.com/questions/28390574/checking-toast-message-in-android-espresso

masud-technope commented 1 year ago

I am testing with API 33, Android 13, does not work. Does anybody have any updates on this problem? It looks like Toast is a red flag for Espresso-based testing. It was such a cool UI!

djbrown commented 1 year ago

I am testing with API 33, Android 13, does not work. Does anybody have any updates on this problem? It looks like Toast is a red flag for Espresso-based testing. It was such a cool UI!

We switched from Toast to SnackBar, might bei an option for you too.

masud-technope commented 1 year ago

Thanks a ton, @djbrown :) I was spending days with the Toast. Now SnackBar worked like a charm!