【Espresso】onData與onView

onView

 /**
   * Creates a {@link ViewInteraction} for a given view. Note: the view has to be part of the view
   * hierarchy. This may not be the case if it is rendered as part of an AdapterView (e.g.
   * ListView). If this is the case, use Espresso.onData to load the view first.
   *
   * <p>This method builds a ViewInteraction object - it does not interact with the application
   * under test at all. It is expected that the caller use the ViewInteraction object to perform an
   * action or assertion.
   *
   * @param viewMatcher used to select the view.
   * @see #onData(org.hamcrest.Matcher)
   */
  // TODO change parameter to type to Matcher<? extends View> which currently causes Dagger issues
  @CheckReturnValue
  @CheckResult
  public static ViewInteraction onView(final Matcher<View> viewMatcher) {
    return BASE.plus(new ViewInteractionModule(viewMatcher)).viewInteraction();
  }

onView可以通過指定的Matcher來定位到要測試的目標元素,它適用於簡單的UI,不適用於AdapterView(指的是ListView,Spinner,GridView等),它有以下限制:

  • 要測試的目標元素必須在可見視圖內,比如說Listview當前可見item爲0-10條,那麼就不能用onView來指定11以上(不在屏幕範圍內)的元素,不然會報錯。
  • 它在滿足上述條件下可以用來測試Listview,但並不保險。

onData

  /**
   * Creates an {@link DataInteraction} for a data object displayed by the application. Use this
   * method to load (into the view hierarchy) items from AdapterView widgets (e.g. ListView).
   *
   * <p>This method builds a DataInteraction object - it does not interact with the application
   * under test at all. It is expected that the caller use the ViewInteraction object to perform an
   * action or assertion.
   *
   * @param dataMatcher a matcher used to find the data object.
   * @return a DataInteraction that will perform an action or assertion.
   */
  @CheckReturnValue
  @CheckResult
  public static DataInteraction onData(Matcher<? extends Object> dataMatcher) {
    return new DataInteraction(dataMatcher);
  }

onData是通過綁定數據來獲取到指定元素,它適用於AdapterView,但不適用於RecyclerView。

  • 可以指定屏幕外的元素
  • 如果指定屏幕外的元素,它將滑動到指定的元素,然後纔會進行後續的操作。

onView使用

@RunWith(AndroidJUnit4.class)
public class EspressoTest {
    @Test
    public void test(){
        onData(withId(R.id.btn)).perform(click());
    }
}

onData使用

  • 如果List的數據源是String類型
List<String>list;

onData(allOf(instanceOf(String.class),is("item0"))).perform(click());

這裏的item0是ListView的第0項的item數據,該數據類型是String類型,allOf將兩條匹配規則整合成一條。

  • 如果List的數據源是HashMap類型
List<Map<String,String>>list;

onData(hasEntry(is("title"),is("content"))).perform(click());

hasEntry的泛型類型是一個Map類型,如下源碼所示:

  /**
   * Creates a matcher for {@link java.util.Map}s matching when the examined {@link java.util.Map} contains
   * at least one entry whose key satisfies the specified <code>keyMatcher</code> <b>and</b> whose
   * value satisfies the specified <code>valueMatcher</code>.
   * <p/>
   * For example:
   * <pre>assertThat(myMap, hasEntry(equalTo("bar"), equalTo("foo")))</pre>
   * 
   * @param keyMatcher
   *     the key matcher that, in combination with the valueMatcher, must be satisfied by at least one entry
   * @param valueMatcher
   *     the value matcher that, in combination with the keyMatcher, must be satisfied by at least one entry
   */
  public static <K, V> org.hamcrest.Matcher<java.util.Map<? extends K, ? extends V>> hasEntry(org.hamcrest.Matcher<? super K> keyMatcher, org.hamcrest.Matcher<? super V> valueMatcher) {
    return org.hamcrest.collection.IsMapContaining.<K,V>hasEntry(keyMatcher, valueMatcher);
  }

它的兩個參數分別對應HashMap的key和value。

  • 如果是Object類型
List<Book>list;

onData(allOf(withBookTitle("item20"),withBookContent("content20"))).perform(click());
public static Matcher<Object> withBookTitle(final String bookTitle){
        return new BoundedMatcher<Object, Book>(Book.class) {

            @Override
            public void describeTo(Description description) {
                description.appendText(bookTitle);
            }

            @Override
            protected boolean matchesSafely(Book item) {
                return bookTitle.equals(item.getTitle());
            }
        };
    }
    public static Matcher<Object> withBookContent(final String bookContent){
        return new BoundedMatcher<Object, Book>(Book.class) {
            @Override
            public void describeTo(Description description) {
                description.appendText(bookContent);
            }

            @Override
            protected boolean matchesSafely(Book item) {
                return bookContent.equals(item.getContent());
            }
        };
    }

該例子的ListView的每個Item項有兩個元素,一個表示title的TextView,一個表示content的TextView,item20表示ListView的第20個item的title。上述Matcher是自定義的Matcher。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章