androidandroid-espressoimagebutton

Espresso : How to test background drawable of an ImageButton


I seemed to have hit rock bottom trying to find a solution of how I can test that my ImageButton has a certain Background drawable in my Espresso test. But I keep getting an error which I pasted below. I've provided as much of the code I can that I thought was relevant.

ImageButton

            <ImageButton
            android:id="@+id/image_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/ic_background_selector"
            android:clickable="true"
            android:src="@drawable/background" />

Selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_background_error" android:state_activated="true" />
<item android:drawable="@drawable/ic_background_okay" android:state_activated="false" />
</selector>

Custom Matcher:

fun matchColor(expectedId: Int): Matcher<View> {
return object : BoundedMatcher<View, ImageButton>(ImageButton::class.java) {
    override fun describeTo(description: Description?) {
        description?.appendText("with text color: ")
        description?.appendValue(expectedId)
    }

    override fun matchesSafely(item: ImageButton?): Boolean {
        return item?.context?.resources?.getDrawable(expectedId)?.constantState == item?.drawable?.constantState
    }

}

}

Test:

        onView(withId(R.id.image_button)).check(matches(matchColor(R.drawable.ic_background_okay)))

I get the following error:

androidx.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: 'with text 
color: <2131165331>' doesn't match the selected view. Expected: with text color: 
<2131165331>Got: "AppCompatImageButton{id=2131296363, ...}

Solution

  • I would advise you to set tags whenever you change the image changes and compare the tags instead of the images itself. If you are not setting tags and can't figure out how to write a custom matcher, you can find your imagebutton via activity and use the same logic you use in your application to compare which image is present right now.

    @Test
    fun test_image_button_compare_success() {
        val activity = getActivityInstance();
        val imageButton = activity?.findViewById((R.id.image_button)) as ImageButton
        assertTrue(1 == 1) //Replace here with your control using image button
    }
    

    Getting activity instance is taken from here

    private Activity getActivityInstance() {
        final Activity[] currentActivity = {null};
    
        getInstrumentation().runOnMainSync(new Runnable() {
            public void run() {
                Collection<Activity> resumedActivity = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
                Iterator<Activity> it = resumedActivity.iterator();
                currentActivity[0] = it.next();
            }
        });
    
        return currentActivity[0];
    }