Using Espresso to Check for Available Changes

I am new to Espresso testing, but there is no way to check for available changes.

I have a tutorial, which is an ImageView Drawable slide show, โ€œtucked intoโ€ a translucent TextView . In my tests, I want to make sure that the right Drawable was inserted into the ImageView tutorial when I clicked the next button.

There is no Matcher default value for checking Drawable s, so I decided to write my own using https://stackoverflow.com/a/4169609/ . Unfortunately, since there is no way to get the ImageView active Drawable identifier, I cannot implement the matchesSafely() implementation.

This may not be the only precedent for testing active Drawable s. What is the tool commonly used for situations like this?

+8
android android-espresso
source share
5 answers

I prefer not to compare bitmaps and instead follow the advice of the answer: https://stackoverflow.com/a/168298/

When setting up a viewable image, also save the identifier for output in your setTag(R.drawable.your_drawable) tag setTag(R.drawable.your_drawable) . Then use the espresso withTag(equalTo(R.drawable.your_drawable)) to check the correct tag.

+4
source share

Please check out this tutorial that I found. Seems to work pretty well https://medium.com/@dbottillo/android-ui-test-espresso-matcher-for-imageview-1a28c832626f#.4snjg8frw

Here is a summary for pasta copies; -)

 public class DrawableMatcher extends TypeSafeMatcher<View> { private final int expectedId; String resourceName; public DrawableMatcher(int expectedId) { super(View.class); this.expectedId = expectedId; } @Override protected boolean matchesSafely(View target) { if (!(target instanceof ImageView)){ return false; } ImageView imageView = (ImageView) target; if (expectedId < 0){ return imageView.getDrawable() == null; } Resources resources = target.getContext().getResources(); Drawable expectedDrawable = resources.getDrawable(expectedId); resourceName = resources.getResourceEntryName(expectedId); if (expectedDrawable == null) { return false; } Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap(); Bitmap otherBitmap = ((BitmapDrawable) expectedDrawable).getBitmap(); return bitmap.sameAs(otherBitmap); } @Override public void describeTo(Description description) { description.appendText("with drawable from resource id: "); description.appendValue(expectedId); if (resourceName != null) { description.appendText("["); description.appendText(resourceName); description.appendText("]"); } } } 

Remember that this only works when your Drawable is BitmapDrawable . If you also have VectorDrawable or another Drawable , you should check this ( imageView.getDrawable() instanceOf XXXDrawable ) and get a bitmap from it. In addition, you have some simple Drawable where you have only one color or you can compare.

To get a VectorDrawable bitmap, for example, you have to draw a VectorDrawable on the canvas and save it in a bitmap (I had some problems drawing VectorDrawable). If you have a StateListDrawable, you can get Drawable from the selected state and repeat the if instanceOf cascade. For other types of Drawable, I have no experience, sorry!

+8
source share

Based on the help of @wolle and @FreewheelNat for comparing (Vector) Drawable:

 public static Matcher<View> withDrawableId(@DrawableRes final int id) { return new DrawableMatcher(id); } public static class DrawableMatcher extends TypeSafeMatcher<View> { private final int expectedId; private String resourceName; public DrawableMatcher(@DrawableRes int expectedId) { super(View.class); this.expectedId = expectedId; } @Override protected boolean matchesSafely(View target) { if (!(target instanceof ImageView)) { return false; } ImageView imageView = (ImageView) target; if (expectedId < 0) { return imageView.getDrawable() == null; } Resources resources = target.getContext().getResources(); Drawable expectedDrawable = resources.getDrawable(expectedId); resourceName = resources.getResourceEntryName(expectedId); if (expectedDrawable != null && expectedDrawable.getConstantState() != null) { return expectedDrawable.getConstantState().equals( imageView.getDrawable().getConstantState() ); } else { return false; } } @Override public void describeTo(Description description) { description.appendText("with drawable from resource id: "); description.appendValue(expectedId); if (resourceName != null) { description.appendText("["); description.appendText(resourceName); description.appendText("]"); } } } 
+2
source share

There is one meaning that contains withBackground() , withCompoundDrawable() , withImageDrawable() Frankie Sardo matches. All loans to him.

And in relation to image identifiers - you can enter R.drawable.image_name , then the drawable identifier will be automatically extracted.

+1
source share

I accept @wolle's answer as valid, but I would like to admit that even for Java it can be even simpler than that. It can be converted to a static function (or a companion in Kotlin), and also clear some outdated code .

In any case, for Kotlin, a code-compressed solution without the deprecated ones would be the following:

  fun drawableIsCorrect(@DrawableRes drawableResId: Int): Matcher<View> { return object : TypeSafeMatcher<View>() { override fun describeTo(description: Description) { description.appendText("with drawable from resource id: ") description.appendValue(drawableResId) } override fun matchesSafely(target: View?): Boolean { if (target !is ImageView) { return false } if (drawableResId < 0) { return target.drawable == null } val expectedDrawable = ContextCompat.getDrawable(target.context, drawableResId) ?: return false val bitmap = (target.drawable as BitmapDrawable).bitmap val otherBitmap = (expectedDrawable as BitmapDrawable).bitmap return bitmap.sameAs(otherBitmap) } } } 

22 lines against 44, huh?

0
source share

All Articles