I'm trying to reach a View which included in include layout with Espresso, within its id. But I always got this error:
androidx.test.espresso.NoMatchingViewException: No views in hierarchy found matching: view.getId() is <2131296553/com.dash.projects.android.karnaugh:id/kmap_variable>
I've tried to find an answer for this problem, by searching any threads within this scope, but I was still unable to find a solution. There is the following links of the thread that I've read:
- Testing included views with Espresso
- Espresso select children of included layout
- Create custom parent view matcher
I launch the test on Karnaugh Map Activity, there is the branch of my Activity:
├── Karnaugh Map Activity
│ ├── Karnaugh Map 2 Variables Fragment // System Under Test
│ ├── Karnaugh Map 3 Variables Fragment
│ ├── Karnaugh Map 4 Variables Fragment
And there is my view xml layouts, within the scope:
<!-- activity_karnaugh_map.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/FillContainer"
tools:context=".views.features.kmap.KarnaughMapActivity">
...
<include
android:id="@+id/inc_kmap_viewpager"
style="@style/ConstraintContainer"
layout="@layout/layout_dot_viewpager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/kmap_appbar" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- layout_dot_viewpager.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
style="@style/FillContainer">
...
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager2"
style="@style/ConstraintContainer"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/dots_indicator" />
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- fragment_kmap_two_variables.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/FillContainer.FillViewPort"
tools:context=".views.features.kmap.branch.KmapTwoFragment">
<include
android:id="@+id/inc_kmap_graphic"
style="@style/FillContainer"
layout="@layout/layout_kmap2_graphic" />
</androidx.core.widget.NestedScrollView>
<!-- layout_kmap2_graphic.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
style="@style/FillContainer.SuperInnerBarrier">
<androidx.constraintlayout.widget.ConstraintLayout
style="@style/FillContainer.SuperInnerBarrier.KmapBackground"
android:layout_height="wrap_content">
<include
android:id="@+id/inc_kmap_variable"
style="@style/HugContent"
layout="@layout/layout_kmap_variable"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include
... />
<include
... />
<include
... />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<!-- layout_kmap_variable.xml -->
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/kmap_variable"
style="@style/HugContent.InnerBarrier.StrokeBackground"
android:theme="@style/TextPrimary.Light.Heading4"
tools:layout_gravity="center"
tools:text="@string/sample_kmap_variable" />
Explanation
On Karnaugh Map Activity xml layout, I'm using view pager to separate logic of Karnaugh Map Variables on a Fragment. Therefore, you can skip first two xml layout that I've given above.
The View that I wanted for this test are TextView on layout_kmap_variable.xml
. To reach the TextView, we should to go through of two include, like below:
> fragment_kmap_two_variables.xml (include#inc_kmap_graphic)
> layout_kmap2_graphic.xml (include#inc_kmap_variable)
> layout_kmap_variable (textview#kmap_variable)
Test Implementation (Espresso)
@RunWith(AndroidJUnit4ClassRunner::class)
class KarnaughMap2VariableTest {
@Before
fun setUp() {
ActivityScenario.launch(KarnaughMapActivity::class.java)
onView(withId(R.id.view_pager2))
.check(matches(isDisplayed()))
.perform(swipeRight())
.check(matches(isCompletelyDisplayed()))
}
@Test
fun chooseKarnaughMap2Variable_activateOrChangeAllCellsValueToOne_verifyTheAnswer() {
onView(withId(R.id.inc_kmap_graphic)).check(matches(isDisplayed()))
onView(withId(R.id.inc_kmap_variable)).check(matches(isDisplayed()))
onView(withId(R.id.kmap_variable)).check(matches(isDisplayed()))
}
When I run the test case, the first two lines on the function has passed the test. But when the compiler go through to the lines 4 onView(withId(R.id.kmap_variable)).check(matches(isDisplayed()))
, an exception will occurs.
Question
I can solve the problem with this view interaction: onView(withText("2 Variables")).check(matches(isDisplayed()))
. Rather than using its ID for accessing the Textview, I ended up it by using its text.
But in some condition we need to access the View by its ID. For example, there is more than one Views that implement same string resource on the screen, it will leading an ambiguous error when we perform an action just by its text.
So, could someone please help me how to solve it, for accessing View by its ID when the View is included by many include layout. Thanks in advance.