6

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

4

6 回答 6

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()方法在第一次尝试时失败。天知道为什么。

以上只是说如果它在第一个滚动时失败,则继续进行。如果它无法在第二个滚动上滚动,那么它实际上会返回失败。

于 2013-12-04T22:32:11.450 回答
5

要查找视图中需要滚动的任何元素,我使用了下面提到的方法,它似乎工作正常。

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();
        }
    }
于 2014-06-30T10:20:40.510 回答
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 布局,则可以更轻松地诊断问题。

于 2013-04-07T18:52:39.520 回答
1

总的来说,我对 's 的运气UiDevicedrag()Scrollable's 方法的运气好。

于 2014-01-22T17:21:17.823 回答
1

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

当您调用 时getChildByText,其流程为:

getChildByText -> scrollIntoView -> scrollForward -> scrollSwipe

scrollSwipe,系统将运行滑动命令,等待,然后在当前屏幕中查找所有AccessibilityEvent并过滤。AccessibilityEvent.TYPE_VIEW_SCROLLED这一步让 UiScrollable 再次滚动或检查到底。

但是bug就在这里,系统无法正确返回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;
}

}
于 2016-08-24T02:16:19.413 回答
0
scrollableObject.scrollIntoView(btn_1);
try {if(scrollableObject.scrollIntoView(btn_1))
    btn_1.click();
}
catch (UiObjectNotFoundException e){
System.out.print("error1: "+e);
}

不确定这是否可以帮助您,但这是我在我的应用程序中所做的。第一行是让它滚动,直到找到 btn_1,然后如果找到对象,它将执行单击它。

于 2013-05-13T02:51:37.473 回答