2013-04-07 88 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; 
    } 
    
    }