13

I'm just getting started with Espresso for testing Android apps, but I'm having some trouble. I have an Activity with a button that replaces a fragment in the usual way:

public void onClick(View v) {
    final FragmentTransaction t = getFragmentManager().beginTransaction();
    t.setCustomAnimations(R.animator.fragment_slide_in_up, 0);
    t.replace(R.id.fragment_container,
        LogInFragment.newInstance(), LogInFragment.TAG)
        .addToBackStack(LogInFragment.TAG);
    t.commit();
}

In my test, I click the button that sends in the new fragment, and then just check that the new fragment is visible.

onView(withId(R.id.login_btn))
    .perform(click());
Thread.sleep(500);
onView(withId(R.id.email_input))
    .check(matches(isDisplayed()));

If I remove the Thread.sleep() from the test, the test fails, even if I remove the setCustomAnimations() from the Activity code.

All animations are turned off on my phone, as per the instructions. My understanding is that Espresso knows about the UI thread status and will wait until everything is ready. But if I do a onView(withId(R.id.widgetOnNewFragment)) it blows up every time. I need to add a Thread.sleep(500) every time I show a new fragment.

Am I missing something? I think I should not have to add dozens of Thread.sleep() to my test code.

Ken DeLong
  • 929
  • 2
  • 8
  • 27
  • 3
    Use IdlingResource – Honza Musil Mar 31 '17 at 18:32
  • 1
    According to https://stackoverflow.com/questions/34503616/android-espresso-idlingresources-and-fragment-activity-transitions?rq=1 , `Fragment` and `Activity transitions` happen on the main thread, so we don't need to implement any `IdlingResource`s. – pvd May 19 '21 at 10:11

1 Answers1

8

While the Espresso framework 'waits' for certain main UI thread activities, animations require the IdlingResource approach (as Honza suggests).

There are good tutorials on this concept, even detailed implementations.

In reality, because animations rarely factor in to functional testing of the UI, most developers disable animations. IMO, this is an anti-pattern because it doesn't map to the real user experience (most people buy a phone and use it with default settings). This is a decision you'll have to make yourself. If you want to include animations as part of your functional requirements, there are ways, but it requires you to reimplement and rewrite your tests.

Paul Bruce
  • 554
  • 2
  • 7
  • 1
    So doing a fragmentTransaction.replace() is always an animation, and always requires an IdlingResource? – Ken DeLong Mar 31 '17 at 21:11
  • yes. my experience is that fragmentTransaction.commit() is async to the main thread, and does not block Espresso from executing. Did you try .commitNow()? The documentation discusses the asynchronous nature of FragmentTransaction use here: https://developer.android.com/reference/android/app/FragmentTransaction.html – Paul Bruce Apr 01 '17 at 13:32
  • 1
    Removing animations is an anti-pattern, but if the final tests are human made that is not a problem. I find it useful to add a layer of non automated tests where i can feel the user interaction with the app and find some glitches not easily detected by automated tests. – MiguelSlv Apr 21 '18 at 12:14
  • 1
    Modifying prod code for testing purposes is also an anti-pattern imo – R. Rincón Apr 23 '21 at 15:37