ArbiterBo
ArbiterBo

Reputation: 91

Forcing action while app not idle in Espresso - Android

A lot of people have asked how to get the Espresso framework to wait for a background task to be finished before performing an action or asserting something. I understand that in those situations, IdlingResource is often the answer.

My question is sort of the opposite. I have a countdown that Espresso waits for by default because a ProgressBar gets updated. During this countdown, I have a sort of "Cancel" button to stop the countdown.

The test I want to write will set up the background task and check that cancel button takes the app back to the previous screen. Right now it waits for the background task to finish before trying to click the cancel button but the cancel button disappears after the task is done.

How would I "force" Espresso to perform an action (click the cancel), even though the app is not idle?

Upvotes: 9

Views: 1228

Answers (1)

L4ry
L4ry

Reputation: 77

To be honest with you, I don't think it is possible. I had the same problem. I fixed it by using UIAutomator to click the (in your case) cancel button.

In my case I had a login button, after which there's a map. The app is never idle after the Login button or even just in the MapFragment (Problem for Espresso), so I had to use UIAutomator for the Login button and to check if the map comes up after logging in.

I popped this into the app's dependencies:

androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'

And in my LoginTest.kt file:

import androidx.test.uiautomator.*
//your imports here

@RunWith(AndroidJUnit4::class)
@LargeTest
class LoginTest {
    @Rule
    @JvmField
    //your rules here
    lateinit var mDevice:UiDevice


    @Before
    fun setUp() {
        //your setUp stuff
        mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

    }

    @Test
    fun checkLogin(){
        onView(withId(R.id.loginBtn)).perform(click())   //goes to LoginFragment

        mDevice.findObject(UiSelector().text("LOGIN")).click()   //clicks login button
        //this is where I had to use the UIAutomator because espresso would never be
        //idle after the login button

        mDevice.wait(Until.findObject(By.text("YOU HAVE LOGGED IN")),15000)
        //this waits until the object with the given text appears, max. wait time is 15 seconds
        //as espresso would still not be idle, I had to check if the login was successful 
        //with (again) the help of UIAutomator
    }

    @After
    fun tearDown() {

    }

}

hope this helps somebody

Upvotes: 2

Related Questions