Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing ViewPager with multiple fragments using android espresso

I am trying to test my app which uses ViewPager. Each page contains fragments but these fragments are not always visible. I want to check visibility of a fragment in the currently visible page.

onView(withId(R.id.container_weather))
    .check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));

But the problem is that espresso looks are all the pages not just the current page and I get the following error:

android.support.test.espresso.AmbiguousViewMatcherException: 'with id: eu.airpatrol.android:id/container_weather' matches multiple views in the hierarchy...

like image 302
Ubaier Bhat Avatar asked Aug 06 '15 13:08

Ubaier Bhat


People also ask

How to show multiple fragments in a viewpager?

A ViewPager allows to show multiple fragments in an activity that can be navigated by either fliping left or right. A ViewPager needs to be feed of either Views or Fragments by using a PagerAdapter.

How do I test a dialog fragment?

Though dialog fragments have UI elements, their layout is populated in a separate window, rather than in the activity itself. For this reason, use FragmentScenario.launch () to test dialog fragments. // Assumes that "MyDialogFragment" extends the DialogFragment class.

What is the use of fragmentmanager in Android?

A FragmentManager manages Fragments in Android, specifically, it handles transactions between fragments. A transaction is a way to add, replace, or remove fragments. getPageTitle (int pos): (optional) Similar to getItem () this methods returns the title of the page at index pos.

How do I trigger UI actions in a fragment under test?

When the FragmentScenario class recreates the fragment under test, the fragment returns to the lifecycle state that it was in before it was destroyed. To trigger UI actions in your fragment under test, use Espresso view matchers to interact with elements in your view: ...


3 Answers

I had the same problem, however using the condition isCompletelyDisplayed() solved this problem as it only takes into account the on-screen views.

So, something like this should work:

onView(allOf(withId(R.id.container_weather), isCompletelyDisplayed()))
.check(matches(withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)));

Note: isDisplayed() works too in some cases but it also takes views off-screen into account and won't work if the ViewPager has any other page pr fragment loaded with the same view id.

like image 107
skbrhmn Avatar answered Oct 21 '22 21:10

skbrhmn


Your tests are failing because of multiple elements with the same id. You can combine conditions using allOf(...). Then use isDisplayed() to check that matched view is visible on the screen. Below example can work:

onView(allOf(
    withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE),
    withId(R.id.container_weather)))
    .check(matches(isDisplayed()));
like image 31
denys Avatar answered Oct 21 '22 20:10

denys


Ran into this exact same problem. I was fortunate because the view hierarchies in my ViewPager can be easily identified by their siblings, so I was able to solve this using the hasSibling matcher, like so:

onView(
    allOf(
        hasSibling(withId(R.id.some_sibling)),
        withId(R.id.field_to_test)
    )
).perform(replaceText("123"));

Not a perfect solution as it can be slightly brittle, but in my case I think it was an acceptable compromise.

like image 3
stork Avatar answered Oct 21 '22 21:10

stork