Android – expresso – cliquant sur une entrée de liste basée sur des objets personnalisés

Espresso est utilisé pour tester automatiquement mon application.

Édition: ci-dessous, vous trouvez un certain nombre de réponses!

  • Comment supprimer la couleur sélectionnée sur glisser sur listview
  • HTML5 Webapp comme icône ou application régulière sur iPhone et Android.
  • Impossible de trouver la propriété 'compile' sur org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler_Decorated@397740e0
  • Comment puis-je gérer plusieurs clients connectés à un serveur à l'aide de sockets?
  • Comment puis-je superposer une ombre portée sur une ScrollView?
  • Erreur de plugin: plugin requis "Support Android" est désactivé
  • Comment puis-je cliquer (dans un script de test Espresso automatisé) sur une entrée dans une longue liste d'objets personnalisés?

    Dans la documentation Espresso, il existe un exemple de LongList. Travailler avec une liste d'objets est ce que je fais normalement. En essayant de nombreuses options pour passer de la carte à l'objet n'a pas donné de bons résultats jusqu'à présent.

    La documentation d'Espresso indique qu'un 'onData' devrait être utilisé. Donc, quelque chose comme:

    onData( myObjectHasContent("my_item: 50")).perform(click()); onView(withId( R.id.selection_pos2)).check(matches(withText("50"))); 

    Mes questions (et je pense qu'elles sont utiles pour la communauté d'apprentissage): – Pouvez-vous écrire un bon Matcher pour cela? – Comment pouvons-nous l'utiliser dans 'onData'?

    Quelle est la situation? À l'écran, j'ai une liste d'objets comme:

     public class MyOjbect { public String content; public int size; } 

    L'adaptateur que j'utilise pour remplir la liste peuplée est:

     public class MyObjectWithItemAndSizeAdapter extends ArrayAdapter<MyObjectWithItemAndSize> { private final Context context; private final List<MyObjectWithItemAndSize> values; ... @Override public View getView(int position, View concertView, ViewGroup parent) { View view = null; if (concertView != null) { view = (LinearLayout) concertView; } else { LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate( R.layout.list_item, parent, false); } TextView itemT = (TextView) view.findViewById( R.id.item_content); itemT.setText( values.get(position).item); TextView sizeT = (TextView) view.findViewById( R.id.item_size); sizeT.setText( "" + values.get(position).size); return view; } } 

  • OkHttp Library - NetworkOnMainThreadException sur une publication simple
  • Comment gérer les changements d'orientation de l'écran lorsqu'il existe un asyntask en cours d'exécution avec Android 4.x
  • Existe-t-il un moyen de donner des codes promo / coupons pour que les gens puissent télécharger votre application gratuitement?
  • Android - Comment puis-je obtenir des préférences partagées à partir d'une autre activité?
  • Comment réaliser l'animation suivante dans la conception de matériel Android?
  • Peut-on accéder au pilote Microphone de mon téléphone Android?
  • 3 Solutions collect form web for “Android – expresso – cliquant sur une entrée de liste basée sur des objets personnalisés”

    Le matcher donné à onData() doit correspondre à la valeur souhaitée renvoyée par Adapter.getItem(int) de ListView souhaité.

    Donc dans votre exemple, le matcher devrait être quelque chose comme ceci:

     public static Matcher<Object> withContent(final String content) { return new BoundedMatcher<Object, MyObjectWithItemAndSize>(MyObjectWithItemAndSize.class) { @Override public boolean matchesSafely(MyObjectWithItemAndSize myObj) { return myObj.content.equals(content); } @Override public void describeTo(Description description) { description.appendText("with content '" + content + "'"); } }; } 

    Une addition à la réponse précédente, je crée une version complète avec 2 types de validations. Cela peut vous aider à comprendre Espresso et Custom Matchers.

    La différence avec l'exemple standard de Espresso LongList est que j'utilise une liste d'objets personnalisés à afficher dans une liste. Faire défiler vers la droite liste-entrée et vérifier le résultat est montré ci-dessous.

    Méthode 1 – la validation contre une chaîne

    Dans le script de test est:

     onData( allOf( instanceOf( MyObjectWithItemAndSize.class), myCustomObjectShouldHaveString( "my_item: 60"))) .perform(click()); // testing the result ... as in the longlist example onView(withId(R.id.selection_pos2)).check(matches(withText("my_item: 60"))); 

    Le matcher est:

     public static Matcher<Object> myCustomObjectShouldHaveString( String expectedTest) { return myCustomObjectShouldHaveString( equalTo( expectedTest)); } private static Matcher<Object> myCustomObjectShouldHaveString(final Matcher<String> expectedObject) { return new BoundedMatcher<Object, MyObjectWithItemAndSize>( MyObjectWithItemAndSize.class) { @Override public boolean matchesSafely(final MyObjectWithItemAndSize actualObject) { // next line is important ... requiring a String having an "equals" method if( expectedObject.matches( actualObject.item) ) { return true; } else { return false; } } @Override public void describeTo(final Description description) { // could be improved, of course description.appendText("getnumber should return "); } }; } 

    Méthode 2: validation contre l'objet (objet complet).

    Dans le script de test, vous trouvez:

     MyObjectWithItemAndSize myObject = new MyObjectWithItemAndSize( "my_item: 60", 11); onData( allOf( instanceOf( MyObjectWithItemAndSize.class), myObjectHasContent( myObject))).perform( click()); onView(withId( R.id.selection_pos2)).check(matches(withText("my_item: 60"))); 

    Le matcher est.

    La ligne la plus importante (j'ai eu des difficultés avec) est en dessous de // ****

     public static Matcher<Object> myObjectHasContent( MyObjectWithItemAndSize expectedObject) { return myObjectHasContent( equalTo( expectedObject)); } //private method that does the work of matching private static Matcher<Object> myObjectHasContent(final Matcher<MyObjectWithItemAndSize> expectedObject) { return new BoundedMatcher<Object, MyObjectWithItemAndSize>(MyObjectWithItemAndSize.class) { @Override public boolean matchesSafely( final MyObjectWithItemAndSize actualObject) { // ****** ... the 'matches'. See below. // this requires the MyObjectWithItemAndSize to have an 'equals' method if( expectedObject.matches( actualObject) ) { return true; } else { return false; } } @Override public void describeTo(final Description description) { description.appendText("getnumber should return "); } }; } 

    Ce qui est très important, c'est que l'objet personnalisé a cette méthode (et je supposer que je suis renversé):

     @Override public boolean equals( Object mob2) { return( (this.item.equals( ((MyObjectWithItemAndSize) mob2).item))); // of course, could have also a check on this.size. } 

    Et il fonctionne!!!! Pfff, a pris un certain temps, mais a surmonté. Merci aussi à Yash F.

    J'ai dû tester et AdapterView avec un adaptateur personnalisé utilisant Espresso 2 aujourd'hui. J'ai fini par utiliser FeatureMatcher:

     private static FeatureMatcher<Product, String> withProductName(final String productName) { return new FeatureMatcher<Product, String>(equalTo(productName), "with productName", "productName") { @Override protected String featureValueOf(Product actual) { return actual.name; } }; } 

    Et puis appeler cette méthode d'utilité à partir d'un test comme suit:

     onData(withProductName("My Awesome Product")) .inAdapterView(withId(R.id.product_list)) .onChildView(withId(R.id.product_title)) .check(matches(withText("My Awesome Product"))); 

    Je pense que FeatureMatcher est génial lorsque vous souhaitez affirmer une propriété spécifique d'un objet de données.

    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.