4

I'm writing UI tests for my application using Espresso. I'd like to test the fact that if I click the back button while a server request is in progress the app must remain where it is.

It seems not to be possible due to the espresso's architecture that makes the tests execution wait if some background operation (like AsyncTask) has been fired.

So, how can I test the following scenario:

  • click on a button that fires an AsyncTask
  • test that while the task is running and I press back button, the app stays there?

Is it possibile?

thank you

thaussma
  • 9,756
  • 5
  • 44
  • 46
Apperside
  • 3,542
  • 2
  • 38
  • 65

2 Answers2

1

That's tricky. With AsyncTasks you cannot use Espresso while the tasks are running. And if you would use something else for background work, Espresso does not wait, and the test finishes before the background job.

A simple workaround would be to "press" the back button without Espresso while the task is running. So, start the task, call Activity.onBackPressed() and after the task finishes use Espresso to check that the Activity is still visible:

// Start the async task    
onView(withId(R.id.start_task_button)).perform(click());

// Then "press" the back button (in the ui thread of the app under test)
mActivityTestRule.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        mActivityTestRule.getActivity().onBackPressed();
    }
});

// Then check that the Activity is still visible
// (will be performed when the async task has finished)
onView(withId(R.id.any_view_on_activity)).check(matches(isDisplayed()));
thaussma
  • 9,756
  • 5
  • 44
  • 46
  • Hello, I'm automating this test so they will not be ran manually and so I cant click manually on the button.. And Calling Activity.onBackPressed() after starting the task will cause a different behaviour because it will be executed after the task, and when the task is finished the back button behaviour is different – Apperside Jul 15 '16 at 07:38
  • I'm aware that the tests are automated and that you cannot click it yourself. When you use the code from my answer, `onBackPressed()` will be executed while the `AsyncTask` is running. But if the task finishes instantly or shortly after being started, it is possible that `onBackPressed()` is called after the task. Did you try my solution? What exactlty does not work? – thaussma Jul 15 '16 at 07:46
  • 1
    I didn't tried it jet, but because I was thinking that when the first instruction of your example is executed, the tests execution stops there and goes forward only when the task is complete. Anyway, I will give it a try – Apperside Jul 15 '16 at 09:29
  • 1
    No the test goes on and `runOnUiThread` is executed directly after clicking. Espresso does not wait after clicking. Espresso waits before performing an action, not after. But the last instruction of my example will be blocked until the task finishes (thats intended). – thaussma Jul 15 '16 at 09:42
  • The `mActivityTestRule.runOnUiThread` does not work for me, it's executed anyway after the `perform(click())` – Nicola Beghin Mar 25 '18 at 16:39
  • In my case, runOnUiThread was not performed while running an AsyncTask. It did when the AsyncTask finished. – aytek Jun 06 '20 at 16:35
0

You can prevent the application from triggering finish() when the back button is pressed. To do so, just override public void onBackPressed() without calling super.onBackPressed(). Just like :

@Override
public void onBackPressed() {
  // super.onBackPressed();
}

Additionally, if you are showing a dialog while executing the task, you can use

myDialog.setCancelable(false);
myDialog.setCanceledOnTouchOutside(false);

to prevent the button from being pushed.

Regards,

Ricardo Vieira
  • 1,738
  • 1
  • 18
  • 26