UiScrollable在Android uiautomator中不起作用

时间:2013-04-07 04:03:54

标签: android uiautomator

有没有人尝试过Android UITesting框架UIAutomator? 当我使用类UiScrollabl“在可滚动对象中查找某些对象时,如果可滚动对象的长度为,则无法找到该对象太长了(需要刷两次才能找到它),比如“设置”应用中的“开发人员选项”。 有没有人有同样的问题?

6 个答案:

答案 0 :(得分: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 :(得分: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();
        }
    }

答案 2 :(得分: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布局,则可以更轻松地诊断问题。

答案 3 :(得分:1)

我通常使用UiDevice的{​​{1}}比使用drag()的方法更幸运。

答案 4 :(得分:1)

我也遇到IDialog只滚动一次,我试着追踪它。 我发现根本原因可能来自系统。

当您致电getChildByText时,其流程为:

getChildByText

getChildByText -> scrollIntoView -> scrollForward -> scrollSwipe 中,系统将运行刷卡命令,等待,而不是在当前屏幕中查找所有scrollSwipe和过滤器AccessibilityEvent。此步骤使UiScrollable再次滚动或最后检查它。

但是错误就在这里,系统无法正确返回AccessibilityEvent.TYPE_VIEW_SCROLLED

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

答案 5 :(得分:0)

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

不确定这是否可以帮到你,但这就是我在我的应用中所做的。第一行是让它滚动直到找到btn_1,然后如果它找到了对象,它就会对它进行点击。