2015-11-17 19 views
8

Sono nuovo per i test dell'Espresso, ma non sembra che esista un modo per testare i cambiamenti disegnabili.Utilizzo di Espresso per testare le modifiche estraibili

Ho un tutorial che è uno ImageViewDrawable slideshow 'nascosto in' un semi-trasparente TextView. Nei miei test, voglio assicurarmi che quando viene premuto il pulsante successivo, l'appropriato Drawable sia stato inserito nel tutorial ImageView.

Non esiste un valore predefinito Matcher per verificare Drawable s, quindi ho deciso di scrivere il mio utilizzando https://stackoverflow.com/a/28785178/981242. Sfortunatamente, poiché non è possibile recuperare l'id di Drawable attivo da ImageView, non è possibile completare l'implementazione matchesSafely().

Questo non può essere l'unico caso d'uso per il test attivo Drawable s. Qual è lo strumento che le persone normalmente usano per situazioni come questa?

risposta

4

preferisco non per confrontare bitmap e seguire invece il consiglio di questa risposta: https://stackoverflow.com/a/14474954/1396068

Durante l'impostazione della visualizzazione dell'immagine drawable, memorizza anche l'ID drawable nel suo tag con setTag(R.drawable.your_drawable). Quindi usa gli abbinamenti withTag(equalTo(R.drawable.your_drawable)) di Espresso per controllare il tag corretto.

8

si prega di controllare questo tutorial ho trovato. sembra funzionare piuttosto bene https://medium.com/@dbottillo/android-ui-test-espresso-matcher-for-imageview-1a28c832626f#.4snjg8frw

Ecco la sintesi per la copia di pasta ;-)

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

Si prega di essere consapevole del fatto che questo funziona solo quando il Drawable è un BitmapDrawable. Se si dispone anche di VectorDrawable o altro Drawable, è necessario verificarlo (imageView.getDrawable() instanceOf XXXDrawable) e ricavarne la bitmap. Tranne che hai una sorta di semplice Drawable in cui hai solo un colore o così puoi confrontare.

Per ottenere la bitmap di un VectorDrawable, ad esempio, è necessario disegnare VectorDrawable su una tela e salvarlo in una bitmap (ho avuto qualche problema quando VectorDrawable è stato colorato). Se si dispone di un oggetto StateListDrawable, è possibile ottenere il Drawable dello stato selezionato e ripetere il caso if instanceOf cascade. Per gli altri tipi disegnabili non ho alcuna esperienza, mi dispiace!

+1

questo non funzionerà se il vostro 'Drawable' non è' BitmapDrawable' che può essere 'GradientDrawable',' 'ColorDrawable' o ShapeDrawable' e molti altri – riwnodennyk

+0

Sì, grazie, ho modificato la mia risposta – wolle

+0

per il confronto vettore Drawable, un semplice il modo è utilizzare getConstantState(). Consulta http://stackoverflow.com/questions/9125229/comparing-two-drawables-in-android. L'ho testato su file vettoriali semplici (dalla collezione di icone di design dei materiali), e funziona bene per loro. – FreewheelNat

1

C'è un problema che contiene withBackground(), withCompoundDrawable(), withImageDrawable() abbinatori da Frankie Sardo. Tutti i crediti per lui.

E per quanto riguarda gli ID immagine - è possibile digitare R.drawable.image_name, quindi l'ID del drawable verrà recuperato automaticamente.

1

Sulla base @wolle e @ l'aiuto di FreewheelNat, per il confronto (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

Accetto la risposta di @wolle come valida, ma vorrei ammettere che, anche per Java, potrebbe essere anche più semplice di quello. Può essere convertito in static function (o in companion in Kotlin) e pulire anche il codice deprecato.

In ogni caso, la soluzione in codice compattato-non-deprecato per Kotlin sarebbe questo:

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 linee vs 44, eh?

Problemi correlati