Say I have a Custom View built from scratch that looks like this:
class CustomTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : View(context, attrs, defStyleAttr, defStyleRes) {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
style = Paint.Style.FILL_AND_STROKE
textSize = 48f
color = Color.BLUE
strokeWidth = 3f
}
override fun onDraw(canvas: Canvas?) {
canvas?.drawText("Text from Custom view", width / 2f, height / 2f, paint)
}
}
This is very simple drawing Text on Canvas. And in a fragment layout, I add a TextView and my CustomText view like the following:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="32dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text from Text View" />
<com.example.testing.views.CustomTextView
android:layout_width="250dp"
android:layout_height="32dp"
android:layout_marginTop="10dp" />
</LinearLayout
My espresso test file looks like:
@RunWith(AndroidJUnit4::class)
class MyFragmentTest {
private lateinit var scenario: FragmentScenario<MyFragment>
@Before
fun setup() {
scenario = launchFragmentInContainer(themeResId = R.style.Theme_Testing)
scenario.moveToState(Lifecycle.State.STARTED)
}
@Test
fun testNormalTextView() { // -> PASSED
onView(withText("Text from Text View")).check(matches(isDisplayed()))
}
@Test
fun testCustomTextView() { // -> FAILED NoMatchingView Exception
onView(withText("Text from Custom View")).check(matches(isDisplayed()))
}
}
When I run the tests on my physical device, it passes only testNormalTextView
but it fails on testCustomTextView
. How do I make these Espresso test pass with Custom Views?
From the official docs, withText()
viewMatcher works with Textviews.
Returns a matcher that matches TextView based on its text property value.
In your case your custom view is extending View
class.
Following are two ways which i will suggest.
withId()
viewMatcher instead of withText()
, passing id of your customview given in xml layout. You need to give id to your custom view in xml. [If you want to check view with specific id, not with the text it holds]In your xml
<com.example.testing.views.CustomTextView
android:id="@+id/my_custom_view"
android:layout_width="250dp"
android:layout_height="32dp"
android:layout_marginTop="10dp" />
In your testFunction
@Test
fun testCustomTextView() {
onView(withId(R.id.my_custom_view)).check(matches(isDisplayed()))
}
Update:
For recyclerview, you can use onData()
instead of onView()
passing matcher in argument.
You can find further info about testing adapterViews
here