UiScrollable not working in Android uiautomator

Is anyone trying to create an Android UITesting framework UIAutomator ? When I use the UiScrollabl "class to search for some objects in a scrollable object, it cannot find the object if the length of the scrollable object is too long (you need to scroll it twice to find it), for example," Developer options "in the Settings application. Someone Does anyone have the same problem?

+6
source share
6 answers

I fixed it by overriding the UiScrollable class.

 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; } } 

I copied the source from: UiScrollable.java (which may be out of date at some point, beware) and just changed the line if(!scrollForward() && x!=0) .

From my observations, in the case of sample code on the Google ui testing page that scrolls the application screen for the settings application, the scrollForwards() method fails on the first try. God knows why.

The above simply says that if it does not work in the first scroll, continue independently. If he fails to scroll the second scroll, he really returns a failure.

+8
source

To find any element in the view where scrolling is required, I used the method described below and it seems to work fine.

 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(); } } 
+4
source

Can you provide more detailed information, for example,

  • What version of adt are you using?
  • What version of Android are I / O tests?

The reason I ask these questions is because UIAutomator has problems with a particular version. For example, I found scrolling issue on devices with Android 4.2.2, which is similar to the one you mentioned. I encoded a workaround when my code scrolls if the standard Android method does not seem to find the element that I expect to be available.

I reproduced the essence of my code here, you will find a complete example at 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."); } } 

Note. I do not know if this code will solve your problem, since I do not have an example of your application. If you can publish your tests and the XML layout of the appropriate user interface, this will help diagnose the problem.

+3
source

I'm more fortunate with UiDevice drag() than with Scrollable methods.

+1
source

I also meet getChildByText only scrolling once, and I am trying to trace it. I believe that the main reason may be from the system.

When you call getChildByText , its stream:

 getChildByText -> scrollIntoView -> scrollForward -> scrollSwipe 

In scrollSwipe system launches a cleanup command, wait for it to find all AccessibilityEvent and the AccessibilityEvent.TYPE_VIEW_SCROLLED filter on the current screen. This step will force UiScrollable to scroll again or check it at the end.

But the error is here, the system cannot return to the right of 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; } ... .. . } 

I think the best way is to override the code and determine the appropriate MaxSearchSwipes , and if the element exceeds this size, make the test unsuccessful.

 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; } } 
+1
source
 scrollableObject.scrollIntoView(btn_1); try {if(scrollableObject.scrollIntoView(btn_1)) btn_1.click(); } catch (UiObjectNotFoundException e){ System.out.print("error1: "+e); } 

Not sure if this can help you, but this is what I am doing in my application. The first line is to make it scroll until it finds btn_1, and then if it finds an object, it clicks on it.

0
source

All Articles