HowieH
HowieH

Reputation: 2612

Testing background color espresso Android

Is it possible to check if the background color matches a given color with espresso?

Update:

I made a custom matcher, similar to what @Irfan suggested, thanks!

public static Matcher<Object> backgroundShouldHaveColor(int expectedColor) {
    return buttondShouldHaveBackgroundColor(equalTo(expectedColor));
}
private static Matcher<Object> buttonShouldHaveBackgroundColor(final Matcher<Integer> expectedObject) {
    final int[] color = new int[1];
    return new BoundedMatcher<Object, Button>( Button.class) {
        @Override
        public boolean matchesSafely(final Button actualObject) {

            color[0] =((ColorDrawable) actualObject.getBackground()).getColor();


            if( expectedObject.matches(color[0])) {
                return true;
            } else {
                return false;
            }
        }
        @Override
        public void describeTo(final Description description) {
            // Should be improved!
            description.appendText("Color did not match "+color[0]);
        }
    };
}

Upvotes: 18

Views: 24126

Answers (8)

rajkumar21
rajkumar21

Reputation: 253

More concise and elegant way of doing in Kotlin with SAM conversion

onView(withId(R.id.tv_login_result)).check{
            view, _ ->
        val actualColor = ((view as MaterialTextView).background as 
                           ColorDrawable).color
        assertEquals(Color.RED, actualColor)
    }

Upvotes: 0

Nehemias G Miranda
Nehemias G Miranda

Reputation: 91

I am late but this might be helpful to someone else

    public static Matcher<View> matchesBackgroundColor(final int expectedResourceId) {
    return new BoundedMatcher<View, View>(View.class) {
        int actualColor;
        int expectedColor;
        String message;

        @Override
        protected boolean matchesSafely(View item) {
            if (item.getBackground() == null) {
                message = item.getId() + " does not have a background";
                return false;
            }
            Resources resources = item.getContext().getResources();
            expectedColor = ResourcesCompat.getColor(resources, expectedResourceId, null);

            try {
                actualColor = ((ColorDrawable) item.getBackground()).getColor();
            }
            catch (Exception e) {
                actualColor = ((GradientDrawable) item.getBackground()).getColor().getDefaultColor();
            }
            finally {
                if (actualColor == expectedColor) {
                    Timber.i("Success...: Expected Color " + String.format("#%06X", (0xFFFFFF & expectedColor))
                            + " Actual Color " + String.format("#%06X", (0xFFFFFF & actualColor)));
                }
            }
            return actualColor == expectedColor;
        }
        @Override
        public void describeTo(final Description description) {
            if (actualColor != 0) { message = "Background color did not match: Expected "
                    +  String.format("#%06X", (0xFFFFFF & expectedColor))
                    + " was " + String.format("#%06X", (0xFFFFFF & actualColor));
            }
            description.appendText(message);
        }
    };
}

I also logged the expected and actual color In hex format which might be helpful.

Usage: onView(withId(R.id.viewId)).check(matches(matchesBackgroundColor(R.color.colorId)));

Upvotes: 5

Mihango K
Mihango K

Reputation: 131

It is possible to to test on color. I created a method to test on TextView background color as below. Also notice that am passing color resource.

 private fun withBackgroundColor(@ColorInt color: Int): Matcher<View> {
        Checks.checkNotNull(color)
        return object : BoundedMatcher<View, TextView>(TextView::class.java) {
            override fun describeTo(description: Description?) {
                description?.appendText("TextView background color to be $color")
            }

            override fun matchesSafely(item: TextView?): Boolean {
                val backgroundColor = item?.background as ColorDrawable
                val colorDrawable = ColorDrawable(ContextCompat.getColor(item.context, color))
                return colorDrawable.color == backgroundColor.color
            }

        }
    }

I create ColorDrawable object from color resource and get color from the object.

Comparing color from resource without the ColorDrawable does not pass. Hope this helps you.

Upvotes: 3

Francesco Santagati
Francesco Santagati

Reputation: 146

private fun hasBackgroundColor(colorRes: Int): Matcher<View> {
    Checks.checkNotNull(colorRes)

    return object : TypeSafeMatcher<View>() {
        override fun describeTo(description: Description?) {
            description?.appendText("background color: $colorRes")
        }

        override fun matchesSafely(item: View?): Boolean {

            val context = item?.context
            val textViewColor = (item?.background as ColorDrawable).color
            val expectedColor: Int?

            if (Build.VERSION.SDK_INT <= 22) {
                expectedColor = context?.resources?.getColor(colorRes)
            } else {
                expectedColor = context?.getColor(colorRes)
            }

            return textViewColor == expectedColor
        }
    }
}

Upvotes: 2

Irfan
Irfan

Reputation: 956

I am not sure about that but we can retrieve the color of some of elements like button and text views `

Button button = (Button) findViewById(R.id.my_button);
Drawable buttonBackground = button.getBackground();

and you can try like this

ColorDrawable b_color = (ColorDrawable) button.getBackground();

and then

int color = b_color.getColor();
if (color == R.color.green) {
    log("color is green");
}

Hope this will get you started.

Upvotes: 11

oshurmamadov
oshurmamadov

Reputation: 265

Another approach to check TextView text's color could be via hasTextColor(int color) as it comes directly from Espresso.

import static android.support.test.espresso.matcher.ViewMatchers.hasTextColor;

onView(withId(R.id.anyTextView)).check(matches(hasTextColor(R.color.red)));

Be aware that this method is currently in Beta for Espresso 3.0.1

Upvotes: 3

pawan singh
pawan singh

Reputation: 79

Here is what i use in my tests

public static Matcher<View> withTextColor(final int color) {
    Checks.checkNotNull(color);
        return new BoundedMatcher<View, TextView>(TextView.class) {
            @Override
            public boolean matchesSafely(TextView textView) {
                return ContextCompat.getColor(getTargetContext(),color)==textView.getCurrentTextColor();
            }
            @Override
            public void describeTo(Description description) {
                description.appendText("with text color: ");
            }
        };
}

and call it as

onView(withId(R.id.price_value)).check(matches(withTextColor(R.color.black)));

Upvotes: 1

denys
denys

Reputation: 6910

In my tests I have the following matcher for testing EditText color:

public static Matcher<View> withTextColor(final int color) {
    Checks.checkNotNull(color);
    return new BoundedMatcher<View, EditText>(EditText.class) {
        @Override
        public boolean matchesSafely(EditText warning) {
            return color == warning.getCurrentTextColor();
        }
        @Override
        public void describeTo(Description description) {
            description.appendText("with text color: ");
        }
    };
}

And usage is :

onView(withId(R.id.password_edittext)).check(matches(withTextColor(Color.RED)));

Upvotes: 29

Related Questions