有人尝试过androidUITesting
框架UIAutomator
吗?当我使用类“在可滚动UiScrollabl
对象中查找某些对象时,如果可滚动对象的长度过长(需要滑动两次才能找到),则无法找到该对象,例如“开发人员选项”中的“设置”应用程序。有人有同样的问题吗?
6 回答
我已经通过覆盖一个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()
方法在第一次尝试时失败。天知道为什么。
以上只是说如果它在第一个滚动时失败,则继续进行。如果它无法在第二个滚动上滚动,那么它实际上会返回失败。
要查找视图中需要滚动的任何元素,我使用了下面提到的方法,它似乎工作正常。
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();
}
}
您能否提供更多详细信息,例如
- 你用的是哪个版本的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 布局,则可以更轻松地诊断问题。
总的来说,我对 's 的运气UiDevice
比drag()
对Scrollable
's 方法的运气好。
我也遇到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;
}
}
scrollableObject.scrollIntoView(btn_1);
try {if(scrollableObject.scrollIntoView(btn_1))
btn_1.click();
}
catch (UiObjectNotFoundException e){
System.out.print("error1: "+e);
}
不确定这是否可以帮助您,但这是我在我的应用程序中所做的。第一行是让它滚动,直到找到 btn_1,然后如果找到对象,它将执行单击它。