2013-04-07 86 views
6

有沒有人試過android UITesting框架UIAutomator? 當我使用類UiScrollabl「查找可滾動對象中的某些對象時,如果對象的可滾動對象的長度過長(需要滑動兩次以找到它),它將無法找到對象,例如「開發人員選項」中的「設置」應用程序。 有沒有人有同樣的問題?UiScrollable在Android中無法使用uiautomator

回答

3

能ADT的版本,您使用的是哪一種?

  • 哪個版本的你提供一些詳細信息,請如

    • 的Android是正在運行的測試?

    我問這些問題的原因是因爲UIAutomator存在一些特定於版本的問題。例如,我發現一個滾動問題運行在Android 4.2.2的設備上,與您提到的類似。我編寫了一個解決方法,我的代碼在執行滾動時,如果標準Android方法似乎沒有找到我期望可用的元素。

    我在這裏複製我的代碼的本質,你會在http://blog.bettersoftwaretesting.com/?p=84

     // The following loop is to workaround a bug in Android 4.2.2 which 
         // fails to scroll more than once into view. 
         for (int i = 0; i < maxSearchSwipes; i++) { 
    
          try { 
           appToLaunch = appViews.getChildByText(selector, nameOfAppToLaunch); 
           if (appToLaunch != null) { 
            // Create a UiSelector to find the Settings app and simulate  
            // a user click to launch the app. 
            appToLaunch.clickAndWaitForNewWindow(); 
            break; 
           } 
          } catch (UiObjectNotFoundException e) { 
           System.out.println("Did not find match for " + e.getLocalizedMessage()); 
          } 
    
          for (int j = 0; j < i; j++) { 
           appViews.scrollForward(); 
           System.out.println("scrolling forward 1 page of apps."); 
          } 
         } 
    

    注意找到完整的例子:我不知道,因爲我沒有這個代碼將解決你的問題有一個你的應用程序的例子。如果您可以發佈測試和相關UI的XML佈局,則可以更輕鬆地診斷問題。

  • +0

    您可能會對下面的修復程序感興趣,重寫uiscrollable類,因爲它可以解決多個地方的問題。 – newfivefour 2013-12-04 22:34:34

    +0

    這個答案適合我...下面的修正沒有 – 2015-01-09 22:18:51

    0
    scrollableObject.scrollIntoView(btn_1); 
    try {if(scrollableObject.scrollIntoView(btn_1)) 
        btn_1.click(); 
    } 
    catch (UiObjectNotFoundException e){ 
    System.out.print("error1: "+e); 
    } 
    

    不知道這是否可以幫助你,但這是我在我的應用程序中所做的。第一行是讓它滾動直到找到btn_1,然後如果它找到了該對象,它將執行一次點擊。

    8

    我已經通過覆蓋UiScrollable類來修復它。

    public class UiScrollable extends com.android.uiautomator.core.UiScrollable { 
    
        public UiScrollable(UiSelector container) { 
         super(container); 
        } 
    
        @Override 
        public boolean scrollIntoView(UiSelector selector) throws UiObjectNotFoundException { 
         if (exists(getSelector().childSelector(selector))) { 
          return (true); 
         } else { 
          System.out.println("It doesn't exist on this page"); 
          // we will need to reset the search from the beginning to start search 
          scrollToBeginning(getMaxSearchSwipes()); 
          if (exists(getSelector().childSelector(selector))) { 
           return (true); 
          } 
          for (int x = 0; x < getMaxSearchSwipes(); x++) { 
           System.out.println("I'm going forward a page: " + x); 
           if(!scrollForward() && x!=0) { // x!=0 is the hack 
            return false; 
           } 
    
           if(exists(getSelector().childSelector(selector))) { 
            return true; 
           } 
          } 
         } 
         return false; 
        }  
    
    } 
    

    我已經複製從源:UiScrollable.java(其可在某些點是過時的,當心)和簡單地改變了if(!scrollForward() && x!=0)線。

    根據我的觀察,在Google的ui測試頁面上滾動應用程序屏幕的示例代碼的情況下,scrollForwards()方法在第一次嘗試時失敗。上帝知道爲什麼。

    以上只是說如果第一次滾動失敗,無論如何進行。如果第二次滾動時滾動失敗,那麼它實際上會返回失敗。

    1

    我一般用UiDevicedrag()Scrollable的方法有更多的運氣。

    +0

    偉大的建議!我遇到了重疊的Scrollable元素,拖動是唯一的解決方案。 – Phil 2015-04-21 14:37:38

    4

    查找和需要滾動的視圖中的任何元素我使用下面提到的方法,它似乎工作正常。

    public void searchForText(String searchText) 
          throws UiObjectNotFoundException { 
         UiScrollable textScroll = null; 
         UiObject text = null; 
         if (searchText != null) { 
          textScroll = new UiScrollable(new UiSelector().scrollable(true)); 
          textScroll.scrollIntoView(new UiSelector().text(searchText)); 
          text = new UiObject(new UiSelector().text(searchText)); 
          text.click(); 
         } 
        } 
    
    +0

    奇怪......這種方法對我來說沒有任何作用......它的行爲與getChildByText一樣...它停止滾動67個元素 – 2015-01-08 07:29:38

    +0

    謝謝。這按預期工作。 – wojciii 2017-02-07 14:24:50

    1

    我也遇到getChildByText只滾動一次,我試圖跟蹤它。 我發現根本原因可能來自系統。

    當你調用getChildByText,其流程爲:

    getChildByText -> scrollIntoView -> scrollForward -> scrollSwipe 
    

    scrollSwipe,系統將運行命令刷卡,等待,比找到所有AccessibilityEvent在當前屏幕過濾AccessibilityEvent.TYPE_VIEW_SCROLLED。這一步使UiScrollable再次滾動或最後檢查它。

    但是錯誤在這裏,系統不能正確返回AccessibilityEvent

    public boolean scrollSwipe(final int downX, final int downY, final int upX, final int upY, 
         final int steps) { 
    
        Runnable command = new Runnable() { 
         @Override 
         public void run() { 
          swipe(downX, downY, upX, upY, steps); 
         } 
        }; 
    
        // Collect all accessibility events generated during the swipe command and get the 
        // last event 
        ArrayList<AccessibilityEvent> events = new ArrayList<AccessibilityEvent>(); 
    
        runAndWaitForEvents(command, 
          new EventCollectingPredicate(AccessibilityEvent.TYPE_VIEW_SCROLLED, events), 
          Configurator.getInstance().getScrollAcknowledgmentTimeout()); 
    
        //**Root cause** 
        //Some times the events list size will be 0 , 
        //but in fact it can scroll again. 
        Log.e(LOG_TAG,"events size = " + events.size()); 
    
        AccessibilityEvent event = getLastMatchingEvent(events, 
          AccessibilityEvent.TYPE_VIEW_SCROLLED); 
    
        if (event == null) { 
         // end of scroll since no new scroll events received 
         recycleAccessibilityEvents(events); 
         return false; 
        } 
        ... 
        .. 
        . 
    } 
    

    我認爲最好的方式是重寫代碼,並確定合適的MaxSearchSwipes,如果該項目是超過此大小的,使測試失敗。

    public class UiScrollableFix extends UiScrollable { 
    
    public UiScrollableFix(UiSelector container) { 
        super(container); 
    } 
    
    @Override 
    public boolean scrollIntoView(UiSelector selector) throws UiObjectNotFoundException { 
        Tracer.trace(selector); 
        // if we happen to be on top of the text we want then return here 
        UiSelector childSelector = getSelector().childSelector(selector); 
        if (exists(childSelector)) { 
         return (true); 
        } else { 
         // we will need to reset the search from the beginning to start search 
         scrollToBeginning(getMaxSearchSwipes()); 
         if (exists(childSelector)) { 
          return (true); 
         } 
    
         for (int x = 0; x < getMaxSearchSwipes(); x++) { 
          Log.e("test", "x=" + x); 
          boolean scrolled = scrollForward(); 
          if (exists(childSelector)) { 
           return true; 
          } 
          //For avoiding the scroll fail. 
          // if (!scrolled && x!=0) { 
          //  return false; 
          // } 
    
         } 
        } 
        return false; 
    } 
    
    }