Reputation: 33
I've written the test, testing if the recycler view is displayed (id: comments_view), but it always fails and I've no idea why. When I'm checking for layout (id: cm), the test passes.
I have the following fragment code:
<layout 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">
<data>
<variable
name="post"
type="com.example.kotlinpostapi.apiObjects.Post" />
<variable
name="comments"
type="java.util.List" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".views.MainActivity"
android:id="@+id/cm">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/comments_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
The test code (I'm navigating to the fragment from another one):
@RunWith(AndroidJUnit4::class)
class CommentsListTest{
@get: Rule
val activityScenario = ActivityScenarioRule(MainActivity::class.java)
@Test
fun testCommentsAreDisplayed() {
onView(withId(R.id.posts_view)).perform(actionOnItemAtPosition<PostAdapter.PostsViewHolder>(0, MyMatchers.clickChildView(R.id.show_comments_button)))
//it fails
onView(withId(R.id.comments_view)).check(matches(isDisplayed()))
//it passes
onView(withId(R.id.cm)).check(matches(isDisplayed()))
}
}
How is it possible, and how can I test my recycler view?
Upvotes: 1
Views: 118
Reputation: 18002
The height of the RecyclerView is set to wrap_content and if the element is not visible at least 90% the test fails.
What you could do is to check one of the RecyclerView children.
I firstly declare the following method:
fun nthChildOf(parentMatcher: Matcher<View?>, childPosition: Int): Matcher<View?>? {
return object : TypeSafeMatcher<View>() {
override fun describeTo(description: Description) {
description.appendText("with $childPosition child view of type parentMatcher")
}
override fun matchesSafely(view: View): Boolean {
if (view.parent !is ViewGroup) {
return parentMatcher.matches(view.parent)
}
val group = view.parent as ViewGroup
return parentMatcher.matches(view.parent) && group.getChildAt(childPosition) == view
}
}
}
with this you can check whether its first child is displayed:
onView(nthChildOf(withId(R.id.comments_view), 0)).check(matches(isDisplayed()))
And to check one element of its children (recyclerview_element_id for example):
onView(allOf(
withId(R.id.recyclerview_element_id),
isDescendantOfA(
nthChildOf(withId(R.id.comments_view), 0))
)).check(matches(isDisplayed()))
Another thing you could try if your RecyclerView expands to the available space of the screen is to change the layout of the RecyclerView to have all the constraints set and with and height to 0dp:
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/comments_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
I have it this way and doing:
onView(withId(R.id.myRecyclerviewId)).check(matches(isDisplayed()))
works for me.
Upvotes: 1