2016-09-25 49 views
3

我是使用濃咖啡的新手。我真的不能得到我想要使用此代碼來測試:如何檢查視圖是否在特定的RecyclerView項目上可見?

onData(withId(R.id.relativelayout_tag)) 
     .inAdapterView(withId(R.id.recyclerview_tag_list)) 
     .onChildView(withId(R.id.imageview_tag)) 
     .atPosition(1) 
     .check(matches(isDisplayed())); 

R.id.imageview_tagR.id.relativelayout_tag一個孩子。 R.id.relativelayout_tag包含我的適配器項目的全部內容。 R.id.recyclerview_tag_list是我的RecyclerView的名稱,我在其中指定了一個特定RecyclerViewAdapter

這是一個非常非常基本的測試。下面是用戶程序:

  1. 選擇,具體,在RecyclerView的第一項(我真的不關心什麼 文本視圖)。也不要建議使用視圖文本來識別第一項。 我不關心適配器項目的內容甚至在某些視圖上放置了獨特的標籤。
  2. 選擇後,應顯示指示器視圖(顯示選擇項目 的ImageView)。

非常基本和簡單。使用Espresso爲這個基本的用戶故事編寫測試非常困難。當我運行特定的測試總是失敗說明這一點:

Caused by: java.lang.RuntimeException: Action will not be performed because the target view does not match one or more of the following constraints: 
(is assignable from class: class android.widget.AdapterView and is displayed on the screen to the user) 
Target view: "RecyclerView{id=2131624115, res-name=recyclerview_tag_list, visibility=VISIBLE, width=480, height=1032, has-focus=false, has-focusable=true, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=true, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=0.0, y=0.0, child-count=15}" 

這是沒有意義的,因爲我有列表中已經顯現。我甚至可以運行這個測試只是罰款:

onView(withId(R.id.recyclerview_tag_list)) 
      .perform(RecyclerViewActions 
      .actionOnItemAtPosition(1, click())); 

以下是完整的測試:

@Test 
public void shouldTagToggleSelected() 
{ 
    onView(withId(R.id.recyclerview_tag_list)) 
      .perform(RecyclerViewActions 
      .actionOnItemAtPosition(1, click())); 

    onData(withId(R.id.relativelayout_tag)) 
     .inAdapterView(withId(R.id.recyclerview_tag_list)) 
     .onChildView(withId(R.id.imageview_tag)) 
     .atPosition(1) 
     .check(matches(isDisplayed())); 

    //onView(withId(R.id.imageview_tag)) 
    //  .check(matches(isDisplayed())); 
} 

我想測試如果指標視圖具有可見性設置爲visible只在特定的項目什麼(或我選擇的任何項目)。

有什麼想法?也許我錯過了一些深刻的東西。

非常感謝!

回答

3

onData不適用RecyclerView因爲RecyclerView不適用AdapterView

您需要使用onView來做出斷言。如果是在回收視圖中的第一個項目,那麼你可以使用這樣的匹配,使您的斷言:

public static Matcher<View> withViewAtPosition(final int position, final Matcher<View> itemMatcher) { 
     return new BoundedMatcher<View, RecyclerView>(RecyclerView.class) { 
      @Override 
      public void describeTo(Description description) { 
       itemMatcher.describeTo(description); 
      } 

      @Override 
      protected boolean matchesSafely(RecyclerView recyclerView) { 
       final RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(position); 
       return viewHolder != null && itemMatcher.matches(viewHolder.itemView); 
      } 
     }; 
} 

而且用法如下:

onView(withId(R.id.recyclerview_tag_list)) 
      .check(matches(withViewAtPosition(1, hasDescendant(allOf(withId(R.id.imageview_tag), isDisplayed()))))); 

請記住,這個匹配如果您的ViewHolder尚未佈置,將會失敗。如果是這種情況,則需要使用RecyclerViewActions滾動到ViewHolder。如果在使用匹配器之前單擊測試中的項目,則不需要滾動。

+0

嗨我編輯你的答案。它應該是'onView(withId(R.id.recyclerview_tag_list))',我知道這就是你的意思。謝謝我現在能夠通過測試。我仍然有點努力想要得到BoundedMatchers的感覺。如果可能,我儘量避免。這似乎不是這種情況。 –

1

檢查不可見的元素線性佈局時,發生異常錯誤。要解決它,我不得不添加與失蹤處理程序如下:

class MyTest { 

     boolean isViewVisible = true; 

     public void test1(){ 

      onView(withRecyclerView(R.id.recycler_view) 
       .atPositionOnView(index, R.id.linear_layout)) 
       .withFailureHandler(new FailureHandler() { 
        @Override 
        public void handle(Throwable error, Matcher<View> viewMatcher){ 

         isViewVisible = false;        
        } 
       }) 
      .check(isVisible()); 

      //wait for failure handler to finish 
      try { 
      Thread.sleep(1000); 
      } catch (InterruptedException e) { 
      e.printStackTrace(); 
      } 

      if(isViewVisible){ 

       //do something 
      } 
     } 
} 

class MyTestUtil { 

    public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) { 

     return new RecyclerViewMatcher(recyclerViewId); 
    } 

    public static ViewAssertion isVisible() { 

     return new ViewAssertion() { 
      public void check(View view, NoMatchingViewException noView) { 
       assertThat(view, new VisibilityMatcher(View.VISIBLE)); 
      } 
     }; 
    } 
} 


public class RecyclerViewMatcher { 
    private final int recyclerViewId; 

    public RecyclerViewMatcher(int recyclerViewId) { 
     this.recyclerViewId = recyclerViewId; 
    } 

    public Matcher<View> atPosition(final int position) { 
     return atPositionOnView(position, -1); 
    } 

    public Matcher<View> atPositionOnView(final int position, final int targetViewId) { 

     return new TypeSafeMatcher<View>() { 
      Resources resources = null; 
      View childView; 

      public void describeTo(Description description) { 
       String idDescription = Integer.toString(recyclerViewId); 
       if (this.resources != null) { 
        try { 
         idDescription = this.resources.getResourceName(recyclerViewId); 
        } catch (Resources.NotFoundException var4) { 
         idDescription = String.format("%s (resource name not found)", 
           new Object[] { Integer.valueOf 
             (recyclerViewId) }); 
        } 
       } 

       description.appendText("with id: " + idDescription); 
      } 

      public boolean matchesSafely(View view) { 

       this.resources = view.getResources(); 

       if (childView == null) { 
        RecyclerView recyclerView = 
          (RecyclerView) view.getRootView().findViewById(recyclerViewId); 
        if (recyclerView != null && recyclerView.getId() == recyclerViewId) { 
         childView = recyclerView.findViewHolderForAdapterPosition(position).itemView; 
        } 
        else { 
         return false; 
        } 
       } 

       if (targetViewId == -1) { 
        return view == childView; 
       } else { 
        View targetView = childView.findViewById(targetViewId); 
        return view == targetView; 
       } 

      } 
     }; 
    } 
} 
相關問題