2015-11-17 11 views
8

Ich bin neu im Espresso-Test, aber es scheint keine Möglichkeit zu geben, umziehbare Änderungen zu testen.Verwenden von Espresso zum Testen von ausformbaren Änderungen

Ich habe ein Tutorial, das ist eine ImageViewDrawable Diashow 'in' eine halbtransparente TextView gesteckt. In meinen Tests möchte ich sicherstellen, dass beim Drücken der nächsten Taste die korrekte Drawable in die ImageView des Lernprogramms eingefügt wurde.

Es gibt keine Standardeinstellung Matcher für Drawable s zu überprüfen, so dass ich meine eigene mit https://stackoverflow.com/a/28785178/981242 schreiben. Da es leider keine Möglichkeit gibt, die ID eines ImageView aktiven Drawable abzurufen, kann ich die matchesSafely() Implementierung nicht abschließen.

Dies kann nicht der einzige Anwendungsfall für das Testen von aktiven Drawable s sein. Was ist das Werkzeug, das Menschen normalerweise für solche Situationen benutzen?

Antwort

4

ich lieber nicht Bitmaps vergleichen und stattdessen diese Ratschläge Antwort folgen: https://stackoverflow.com/a/14474954/1396068

Wenn die Image Einstellung Ansicht Zeichnungsfähig, speichern Sie auch die ID in seinem Tag mit setTag(R.drawable.your_drawable). Dann nutzen Sie withTag(equalTo(R.drawable.your_drawable)) Matcher des Espressos für den richtigen Tag zu überprüfen.

8

Bitte überprüfen Sie diese Anleitung, die ich gefunden habe. Scheint ziemlich gute Pasta https://medium.com/@dbottillo/android-ui-test-espresso-matcher-for-imageview-1a28c832626f#.4snjg8frw

Hier ist die Zusammenfassung für die Kopie zu arbeiten ;-)

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("]"); 
     } 
    } 
} 

Bitte beachten Sie, dass dies nur funktioniert, wenn Ihr Drawable ist ein BitmapDrawable. Wenn Sie auch VectorDrawable oder andere Drawable haben, müssen Sie dies überprüfen (imageView.getDrawable() instanceOf XXXDrawable) und die Bitmap daraus holen. Außer Sie haben eine Art einfaches Drawable, wo Sie nur eine Farbe haben oder so können Sie vergleichen.

Um die Bitmap eines VectorDrawable zum Beispiel zu bekommen, müssen Sie das VectorDrawable auf ein Canvas zeichnen und es in ein Bitmap speichern (ich hatte Probleme, wenn VectorDrawable getönt war). Wenn Sie eine StateListDrawable haben, können Sie die Drawable des ausgewählten Status abrufen und Ihre if instanceOf-Kaskade wiederholen. Für andere Drawable Typen habe ich keine Erfahrung, sorry!

+1

wird nicht funktionieren, wenn Ihr 'Drawable' ist nicht' BitmapDrawable' was sein kann 'GradientDrawable',' ColorDrawable' oder 'ShapeDrawable' und viele andere – riwnodennyk

+0

Ja danke, bearbeitet ich meine Antwort – wolle

+0

Für Vector Drawable Vergleich, eine einfachere Weg ist es, getConstantState() zu verwenden. Siehe http://stackoverflow.com/questions/9125229/comparting-tow-drawables-in-android. Ich habe es auf einfachen Vektor-Zeichenvorlagen (aus der Material Design Icons Sammlung) getestet, und es funktioniert gut für sie. – FreewheelNat

1

Es gibt einen Kern, der withBackground(), withCompoundDrawable(), withImageDrawable() Matcher von Frankie Sardo enthält. Alle Kredite an ihn.

Und in Bezug auf Bild-IDs - Sie können R.drawable.image_name eingeben, dann die ID des ziehbar automatisch abgerufen werden.

1

Basierend auf @wolle und @ FreewheelNat Hilfe, zum Vergleichen (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("]"); 
     } 
    } 
} 
0

Ich akzeptiere die Antwort von @wolle als gültig, aber ich würde gerne zugeben, dass sogar für Java, könnte es sogar einfacher als das sein. Es kann in ein static function (oder ein companion in Kotlin) umgewandelt werden und reinigt auch einigen veraltete Code.

Wie auch immer, der Code dichteten-nicht-veraltete Lösung für Kotlin sein würde:

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 Linien vs 44, nicht wahr? Diese

Verwandte Themen