5

I'm trying to assert whether the correct image is displayed on an image view in Android using Espresso. The images were provided as SVG and converted to vector drawable directly using Android Studio converter. My custom matcher has successful tests for some of the images but not for other ones. If I swap the SVG XML files then the results get inverted with the ones who failed succeeding now which makes me suspect it could be something to do with checking the SVG itself maybe due to the amount of characters for some of the path as when I delete some lines that contain more characters than the other ones it works but not really sure how to properly fix that.

This is the SVG that works

    <vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="80dp"
    android:height="80dp"
    android:viewportWidth="80"
    android:viewportHeight="80">
  <path
      android:pathData="M37.2,37.1m-34.85,0a34.85,34.85 0,1 1,69.7 0a34.85,34.85 0,1 1,-69.7 0"
      android:fillColor="#fff"/>
  <path
      android:pathData="M49.22,19.23h2.67A4.79,4.79 0,0 1,56.67 24V53.39a4.79,4.79 0,0 1,-4.78 4.77H22.51a4.79,4.79 0,0 1,-4.78 -4.77V24a4.79,4.79 0,0 1,4.78 -4.77h3.2"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M45.37,24.93a8.9,8.9 0,1 1,-8.9 -8.9A8.9,8.9 0,0 1,45.37 24.93Z"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M35.88,25.46L40.08,21.72"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
</vector>

But this is the SVG that doesn't work

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="80dp"
    android:height="80dp"
    android:viewportWidth="80"
    android:viewportHeight="80">
  <path
      android:pathData="M37.12,37.28m-34.85,0a34.85,34.85 0,1 1,69.7 0a34.85,34.85 0,1 1,-69.7 0"
      android:fillColor="#fff"/>
  <path
      android:pathData="M34.37,44.93h8.46a3,3 0,0 0,3 -3h0a3,3 0,0 0,-3 -3H34.37"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M34.37,51h8.46a3,3 0,0 0,3 -3h0a3,3 0,0 0,-3 -3H34.37"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M28.6,57H27.54A16.27,16.27 0,0 1,19.62 55h0"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M34.37,51H41.1a3,3 0,0 1,3 3h0a3,3 0,0 1,-3 3H34.37"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M47.31,38.87h8a3.09,3.09 0,0 0,3.11 -2.81,3 3,0 0,0 -0.88,-2.36 3,3 0,0 0,-2.14 -0.89H30.84A1.06,1.06 0,0 1,30.09 31l6.07,-6.07a3.09,3.09 0,0 0,0.19 -4.21,3 3,0 0,0 -4.41,-0.13L18.19,34.33c-6.2,6.21 -6.43,16 1.43,20.65"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M54.91,43.54s3.42,4 3.42,7.05a3.42,3.42 0,0 1,-6.84 0c0,-3 3.42,-7.05 3.42,-7.05"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M54.8,48.13a5.3,5.3 0,0 0,-0.52 2,1.79 1.79,0 0,0 0.79,1.5"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M54.91,35.39L54.91,35.84"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M54.91,25.3L54.91,29.03"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M34.37,51a3,3 0,0 1,-3 -3h0a3,3 0,0 1,3 -3"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M34.37,57a3,3 0,0 1,-3 -3h0a3,3 0,0 1,3 -3"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M34.37,44.93a3,3 0,0 1,-3 -3h0a3,3 0,0 1,3 -3"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
  <path
      android:pathData="M58.13,18.56v4.6A2.14,2.14 0,0 1,56 25.3H53.83a2.14,2.14 0,0 1,-2.14 -2.14v-4.6"
      android:strokeWidth="1.97"
      android:fillColor="#00000000"
      android:strokeColor="#89d3dd"
      android:strokeLineCap="round"/>
</vector>

This is my custom matcher

public class EspressoTestsMatchers {

    public Matcher<View> withDrawable(final int resourceId) {
        return new DrawableMatcher(resourceId);
    }

    public Matcher<View> noDrawable() {
        return new DrawableMatcher(-1);
    }
}

public class DrawableMatcher extends TypeSafeMatcher<View> {
    private final int expectedId;

    public DrawableMatcher(int resourceId) {
        super(View.class);
        this.expectedId = resourceId;
    }

    @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);
        if (expectedDrawable == null) {
            return false;
        }
        Bitmap bitmap = getBitmap(imageView.getDrawable());
        Bitmap otherBitmap = getBitmap(expectedDrawable);
        return bitmap.sameAs(otherBitmap);
    }

    private Bitmap getBitmap(Drawable drawable) {
        Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
                drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
        drawable.draw(canvas);
        return bitmap;
    }

    @Override
    public void describeTo(Description description) {

    }
}

Called this way

 onView(withId(R.id.rv_metrics)).perform(actionOnItemAtPosition(0, click()));
 onView(withId(R.id.iv_type)).check(matches(new EspressoTestsMatchers().withDrawable(R.drawable.ic_metrics_dialog_weight)));

Thanks very much.

Update

Tried also to convert the SVG to Bitmap instead and do the assertion only then but for some reason getting the item drawable still doesn't make the assertion pass.

 BackgroundDrawableMatcher2(Drawable expectedDrawable) {
        super(View.class);
        mExpectedDrawable = expectedDrawable;
    }

    @Override
    protected boolean matchesSafely(View item) {

        Drawable drawable = ContextCompat.getDrawable(getTargetContext(), R.drawable.ic_metrics_dialog_weight); // Hardcoding this makes the assertion work
        ImageView imageView = (ImageView) item;
        return getBitmap2(imageView.getDrawable()).sameAs(getBitmap2(mExpectedDrawable));  // Getting the item this way instead doesn't though :(
    }

These are the lines that need to be commented out to make my test pass

enter image description here

Francislainy Campos
  • 1,743
  • 11
  • 36

1 Answers1

2

For some reason changing the code from setImageDrawable(AppCompatResources) to setImageResource has solved the issue.

//ivDialogType.setImageDrawable(AppCompatResources.getDrawable(Objects.requireNonNull(getContext()), R.drawable.ic_metrics_dialog_weight));
ivDialogType.setImageResource(R.drawable.ic_metrics_dialog_weight);

Alternatively setting a tag for the image may be a good option as well as of this SO question.

Francislainy Campos
  • 1,743
  • 11
  • 36