32

In Espresso class:

@Rule
var mIntentsRule = IntentsTestRule(MainActivity::class.java)

@Test
fun test_backButton() {
    onView(withId(R.id.NEXT_ACTIVITY)).perform(scrollTo(), click())
    Espresso.pressBack()
}

In Activity:

@Override
public void onBackPressed() {
    Log.d("TEST_pressBack", "inside onBackPressed()");
    do_something();
    super.onBackPressed();
}

@Override
public void finish() {
    Log.d("TEST_pressBack", "inside finish()");
    super.finish();
}

When I call the Espresso test method the execution goes directly to finish().

When I press the back button (with my hand) in the Activity the execution goes firstly in onBackPressed() and then to finish(). How can I test the function onBackPressed() with Espresso? Thanks!

EDIT: It is my error. The problem was that in Activity in which I wanted to call pressBack the onscreen keyboard was opened. When the soft keyboard is open then the press-button does not call onBackPressed but instead makes the keyboard non-displayed. I tried with two pressBack() in a row and it worked correctly:

@Rule
public IntentsTestRule<MainActivity> mIntentsRule = new IntentsTestRule<>(MainActivity.class);

@Test
public void test_backButton(){
onView(withId(R.id.NEXT_ACTIVITY)).perform(scrollTo(), click());
   Espresso.pressBack();

   //The extra pressBack()
   Espresso.pressBack();
}
hannes ach
  • 16,247
  • 7
  • 61
  • 84
billst
  • 649
  • 1
  • 8
  • 14

2 Answers2

54

It looks like the Espresso.pressBack() method does just work the way you expect it if you are not in the root activity. When you take a look at it's implementation comment:

  /**
  * Press on the back button.
  *
  * @throws PerformException if currently displayed activity is root activity, since pressing back
  *         button would result in application closing.
  */
  public static void pressBack() {
        onView(isRoot()).perform(ViewActions.pressBack());
  }

I tested it and it works fine if you are doing this in an activity that is not your root activity. If you want to do it there, I would suggest you use ui-automator instead (ui-automator is perfectly usable inside espresso tests):

Add this to your gradle:

androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'

And then do this in your test:

UiDevice mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
mDevice.pressBack();
stamanuel
  • 3,731
  • 1
  • 30
  • 45
  • 3
    It is my error. The problem was that in Activity on which I wanted to call pressBack the onscreen keyboard was opened. When the soft keyboard is open then the press-button does not call onBackPressed but instead makes the keyboard non-displayed. I tried with two pressBack() and it worked correctly – billst Mar 20 '17 at 19:54
  • 2
    `Espresso.closeSoftKeyboard()` would have been the answer to the above question, but yours is a perfect answer to what I was searching for. Thanks a lot! :-) And for future readers here is the androidx version: `androidTestImplementation 'androidx.test.uiautomator:uiautomator:2.2.0'` – StefanTo Jan 10 '19 at 13:29
  • 2
    note there is `Espresso.pressBackUnconditionally()` – hmac Feb 26 '20 at 13:44
  • My activity overrrides `onBackPressed` to change viewPager current position. However, when I use `Espresso.pressBack()` it closes the app instead of changing the viewPager current position. Any idea why this happens? – Inas Oct 11 '20 at 19:16
3

@billst you are right, i too had the same problem with soft keyboard open, i debugged after reading your comment and better solution would be to use ViewAction.closeSoftKeyboard() instead of using back press twice.

@Test
public void afterStartedEditing_dialogDisplayed_when_home_or_back_pressed() {
    //find view
    onView(withId(R.id.add_pet_breed))
            .perform(click())
            .perform(closeSoftKeyboard());
    onView(isRoot()).perform(pressBack());

    //check assertion
    onView(withText(R.string.discard))
            .check(matches(isDisplayed()));
}
KingKongCoder
  • 600
  • 4
  • 15