How to get EditText View from multiple identical id’s from a reused Fragment with Espresso?

Issue

I’m trying to use onView() to get an EditText view that lives inside of a fragment but every EditText in each fragment has the same id.

Given this pseudo-code:

<Activity>
    <Fragment>
         <EditText android:id"@+id/input" />
    </Fragment>
    <Fragment>
         <EditText android:id"@+id/input" />
    </Fragment>
    <Fragment>
         <EditText android:id"@+id/input" />
    </Fragment>
</Activity>

In my test case, I’m doing

onView(withId(R.id.input)).perform(typeText("foo"));

On run, I’m getting with id: com.foo.bar.foobar:id/input' matches multiple views in the hierarchy.. The view hierarchy is below: (I moved the ‘MATCHES’ before the element for readability)

View Hierarchy:
+>DecorView{id-1, visibilityVISIBLE, width1080, height1920, has-focustrue, has-focusabletrue, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count2} 
|
+->LinearLayout{id-1, visibilityVISIBLE, width1080, height1794, has-focustrue, has-focusabletrue, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count2} 
|
+-->ViewStub{id16909295, res-nameaction_mode_bar_stub, visibilityGONE, width0, height0, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0} 
|
+-->FrameLayout{id-1, visibilityVISIBLE, width1080, height1794, has-focustrue, has-focusabletrue, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count1} 
|
+--->FitWindowsLinearLayout{id2131427402, res-nameaction_bar_root, visibilityVISIBLE, width1080, height1794, has-focustrue, has-focusabletrue, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count2} 
|
+---->ViewStubCompat{id2131427403, res-nameaction_mode_bar_stub, visibilityGONE, width0, height0, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0} 
|
+---->ContentFrameLayout{id16908290, res-namecontent, visibilityVISIBLE, width1080, height1794, has-focustrue, has-focusabletrue, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count1} 
|
+----->ConstraintLayout{id2131427422, res-nameconstraintLayout, visibilityVISIBLE, width1080, height1794, has-focustrue, has-focusabletrue, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count7} 
|
+------>AppCompatTextView{id2131427423, res-namestepHeader, visibilityVISIBLE, width321, height140, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x380.0, y168.0, textStep 1:, input-type0, ime-targetfalse, has-linksfalse} 
|
+------>AppCompatTextView{id2131427425, res-namestepTitle, visibilityVISIBLE, width521, height88, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x280.0, y361.0, textBasic Information, input-type0, ime-targetfalse, has-linksfalse} 
|
+------>AppCompatTextView{id2131427426, res-namestepInstruction, visibilityVISIBLE, width141, height71, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x470.0, y712.0, textName, input-type0, ime-targetfalse, has-linksfalse} 
|
+------>AppCompatButton{id2131427427, res-namenextButton, visibilityVISIBLE, width231, height126, has-focustrue, has-focusabletrue, has-window-focustrue, is-clickabletrue, is-enabledtrue, is-focusedtrue, is-focusabletrue, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x425.0, y1479.0, textNext, input-type0, ime-targettrue, has-linksfalse} 
|
+------>AppCompatButton{id2131427424, res-namebackButton, visibilityVISIBLE, width231, height126, has-focusfalse, has-focusabletrue, has-window-focustrue, is-clickabletrue, is-enabledtrue, is-focusedfalse, is-focusabletrue, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x21.0, y21.0, textBack, input-type0, ime-targetfalse, has-linksfalse}
|
+------>ConstraintLayout{id2131427428, res-nameprogressBarContainer, visibilityVISIBLE, width1080, height105, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y1689.0, child-count2}
|
+------->AppCompatTextView{id2131427429, res-nameprogressBar, visibilityVISIBLE, width1080, height105, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, textProgress bar, input-type0, ime-targetfalse, has-linksfalse}
|
+------->View{id2131427430, res-nameprogressIndicator, visibilityVISIBLE, width154, height11, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y94.0}
|
+------>ConstraintLayout{id2131427431, res-namestepContainer, visibilityVISIBLE, width1080, height696, has-focusfalse, has-focusabletrue, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y783.0, child-count6}
|
+------->ConstraintLayout{id2131427436, res-nameviewStepInput, visibilityVISIBLE, width1080, height696, has-focusfalse, has-focusabletrue, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count1}
|
****MATCHES****
+-------->AppCompatEditText{id2131427437, res-nameuserInput, visibilityVISIBLE, width1038, height118, has-focusfalse, has-focusabletrue, has-window-focustrue, is-clickabletrue, is-enabledtrue, is-focusedfalse, is-focusabletrue, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectiontrue, editor-info[inputType0x1 imeOptions0xc000005 privateImeOptionsnull actionLabelnull actionId0 initialSelStart0 initialSelEnd0 initialCapsMode0x0 hintTextnull labelnull packageNamenull fieldId0 fieldNamenull extrasnull hintLocalesnull contentMimeTypesnull ], x21.0, y289.0, text, input-type1, ime-targetfalse, has-linksfalse} 
|
+------->ConstraintLayout{id2131427436, res-nameviewStepInput, visibilityGONE, width0, height0, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count1}
|
+-------->GridView{id2131427439, res-nameselector_grid, visibilityVISIBLE, width0, height0, has-focusfalse, has-focusabletrue, has-window-focustrue, is-clickabletrue, is-enabledtrue, is-focusedfalse, is-focusabletrue, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count0}
|
+------->ConstraintLayout{id2131427436, res-nameviewStepInput, visibilityGONE, width0, height0, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count1}
|
****MATCHES****
+-------->AppCompatEditText{id2131427437, res-nameuserInput, visibilityVISIBLE, width0, height0, has-focusfalse, has-focusabletrue, has-window-focustrue, is-clickabletrue, is-enabledtrue, is-focusedfalse, is-focusabletrue, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectiontrue, editor-info[inputType0x1 imeOptions0xc000005 privateImeOptionsnull actionLabelnull actionId0 initialSelStart0 initialSelEnd0 initialCapsMode0x0 hintTextnull labelnull packageNamenull fieldId0 fieldNamenull extrasnull hintLocalesnull contentMimeTypesnull ], x0.0, y0.0, text, input-type1, ime-targetfalse, has-linksfalse} 
|
+------->ConstraintLayout{id2131427436, res-nameviewStepInput, visibilityGONE, width0, height0, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count1}
|
+-------->GridView{id2131427439, res-nameselector_grid, visibilityVISIBLE, width0, height0, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickabletrue, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count0}
|
+------->ConstraintLayout{id2131427436, res-nameviewStepInput, visibilityGONE, width0, height0, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count1}
|
+-------->GridView{id2131427439, res-nameselector_grid, visibilityVISIBLE, width0, height0, has-focusfalse, has-focusabletrue, has-window-focustrue, is-clickabletrue, is-enabledtrue, is-focusedfalse, is-focusabletrue, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count0}
|
+------->ConstraintLayout{id2131427436, res-nameviewStepInput, visibilityGONE, width0, height0, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y0.0, child-count1}
|
****MATCHES****
+-------->AppCompatEditText{id2131427437, res-nameuserInput, visibilityVISIBLE, width0, height0, has-focusfalse, has-focusabletrue, has-window-focustrue, is-clickabletrue, is-enabledtrue, is-focusedfalse, is-focusabletrue, is-layout-requestedtrue, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectiontrue, editor-info[inputType0x1 imeOptions0xc000005 privateImeOptionsnull actionLabelnull actionId0 initialSelStart0 initialSelEnd0 initialCapsMode0x0 hintTextnull labelnull packageNamenull fieldId0 fieldNamenull extrasnull hintLocalesnull contentMimeTypesnull ], x0.0, y0.0, text, input-type1, ime-targetfalse, has-linksfalse} 
|
+->View{id16908336, res-namenavigationBarBackground, visibilityVISIBLE, width1080, height126, has-focusfalse, has-focusablefalse, has-window-focustrue, is-clickablefalse, is-enabledtrue, is-focusedfalse, is-focusablefalse, is-layout-requestedfalse, is-selectedfalse, root-is-layout-requestedfalse, has-input-connectionfalse, x0.0, y1794.0}
|
at dalvik.system.VMStack.getThreadStackTrace(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:1566)
at android.support.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:92)
at android.support.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:56)
at android.support.test.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:184)
at android.support.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:115)
at android.support.test.espresso.ViewInteraction.perform(ViewInteraction.java:87)
at com.newfoundry.skyline.facialrecognitionkioskapp.ActivityRegistrationScreenTest.testFilledInputFieldShouldIncrementCurrentStepOnNext(ActivityRegistrationScreenTest.java:73)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at android.support.test.internal.statement.UiThreadStatement.evaluate(UiThreadStatement.java:55)
at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:270)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1932)

I’ve tried doing:

EditText input  mActivity.getSupportFragmentManager()
            .findFragmentByTag("foo")
            .getView()
            .findViewById(R.id.input);

onView(withId(input)); 

But am running into issues with that as well. I haven’t been able to find anything addressing this specific issue. Any help would be tremendously appreciated.

Solution

From my understanding, you have to differentiate the TextViews in some way. Assume the first fragment has the id “fragment1”, the second fragment has the id “fragment2”, and so on.

Then you could use

onView(allOf(withParent(withId(R.id.fragment1)),instanceOf(EditText.class))).perform(typeText("foo"));

to only select the single TextView in that fragment and use it in your test case.

Answered By – Zack

Leave a Comment