如何使用Google UiAutomator按两次按钮?

时间:2013-07-01 02:18:09

标签: java android automated-tests avd uiautomator

我使用以下脚本在Android中使用UiAutomator在计算器中输入“33”。但是,只接受第一个'3',第二个按下完全被忽略。

import com.android.uiautomator.core.*;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;

public class MyFirstUiAutomatorTest extends UiAutomatorTestCase {
    UiObject getByDescription(String description) {
        return new UiObject(new UiSelector().description(description));
    }

    UiObject getByText(String description) {
        return new UiObject(new UiSelector().text(description));
    }

    UiObject scrollableGetByText(String text ) throws UiObjectNotFoundException {
            UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true));
            uiScrollable.setAsHorizontalList();
            return uiScrollable.getChildByText(new UiSelector().className(
                    android.widget.TextView.class.getName()),
                    text);      
    }

    public void testStuff() throws UiObjectNotFoundException {
        getUiDevice().pressHome();
        getByDescription("Apps").clickAndWaitForNewWindow();
        getByText("Apps").click();
        scrollableGetByText("Calculator").clickAndWaitForNewWindow();

        // pressing '+' and '=' effectively clears the previous input
        getByText("+").click();
        getByText("=").click();
        getByText("3").click();
        // this second '3' is ignored
        getByText("3").click();
    }
}

我在第一次点击后尝试添加睡眠2秒,方法是:

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

......但这并没有改变任何事情。

我也试过点击2'3之间的另一个按钮,即:

        new UiObject(new UiSelector().text("3")).click();
        new UiObject(new UiSelector().className("android.widget.EditText")).click();
        new UiObject(new UiSelector().text("3")).click();

......但这也不起作用。

想法?

(注意:在AVD中使用Android 4.1.2;在Ubuntu linux 12.04上运行)

编辑,按照Rami的观察,我尝试了以下操作,为同一描述的第二个请求重用相同的UiObject对象:

HashMap<String,UiObject> objectByText = new HashMap<String,UiObject>(); 
UiObject getByText(String description) {
    if( objectByText.containsKey(description)) {
        System.out.println("" + objectByText.get(description) );
        return objectByText.get(description);
    }
    System.out.println("Created new object for [" + description + "]");
    UiObject object = new UiObject(new UiSelector().text(description));
    objectByText.put(description, object );
    System.out.println("" + object );
    return object;
}

...但是它没有用,即使它每次都明显重复使用相同的UiObject,因为它只会说“为[3]创建一个新对象”。

然后我尝试了UiDevice.click()'技巧',再次按照Rami的观察创建一个函数'click':

void click(UiObject target ) throws UiObjectNotFoundException {
    Rect rect = target.getBounds();
    System.out.println("rect: " + rect );
    getUiDevice().click(rect.centerX(), rect.centerY());
}

然而,这对我来说也不起作用:只显示第一个'3',第二个被忽略,即使两个点击明显位于同一位置,因为rect:输出位置相同。如果我手动点击“3”,使用我自己的桌面鼠标,则两个3都显示正常。

我还尝试在点击之间添加两秒Thread.sleep(),但仍然只为我出现了一个“3”。

5 个答案:

答案 0 :(得分:4)

不要只按文字搜索,而是尝试按文字和课程搜索。 这是一个这样做的示例方法。

Uiobject getByTextAndClass(String text, String className) {
    return new UiObject(new UiSelector().text(text).className(className));
}

然后,如果您尝试将此方法用于其上带有数字3的计算器按钮:

getByTextAndClass("3", android.widget.Button.class.getName()).click();

您可以使用UiAutomatorViewer工具:{android-sdk} /tools/uiautomator.bat来检查不同UiObjects的类名和其他属性。

这适用于我的4.2.2设备,但我也在下载4.1.2以在那里进行测试。

我在4.1.2 AVD上尝试过,它可以在我的Windows机器上运行。

答案 1 :(得分:2)

我现在发现了一个小问题来解决这个问题。每次运行测试时都要获得边界,这样它就不会以设备为中心,并且会在运行中适应。

UiObject obj1 = new UiObject(new UiSelector().text("4"));

  Rect four = obj1.getBounds();

  getUiDevice().click(four.centerX(), four.centerY());

答案 2 :(得分:2)

这个问题似乎与UiObject的设置方式有关。据我所知,UiObject的一个实例似乎并没有引用屏幕上的特定对象。它更像是在定义UiObject时UiSelector所指向的实例。这里的关键是每次调用对象时,它都会搜索符合UiSelector要求的新项目。

证据:

UiObject ok = new UiObject(new UiSelector().text("OK"));
ok.click();
// clicks a button with the text ok on the page
// Navigate to some different page with a button with the text ok
ok.click();
// this ok button on a completely different page is still clicked

因此,我认为Rami的解决方法实际上可能采用正确的方法(通过坐标存储对象的位置并单击该位置的中心)。关于Rami的解决方法需要注意的重要事项,保存坐标/矩形一次,然后在需要引用对象时重复使用坐标/矩形。在同一个对象上多次使用obj.getBounds()似乎不起作用。

此外,在UiObject实例化期间已经传递的项目的记录似乎存储在应用程序中。运行两次测试以找到UiObject(例如设置警报页面中的按钮4)并单击它失败的方式与找到UiObject并单击两次的测试相同。这意味着对象查询的数据必须存储在设备上,因为重置UIautomator没有任何区别。

答案 3 :(得分:1)

我有同样的问题,看起来像寻找具有相同文本的另一个UI元素。我正在尝试自动创建一个警报但是当时间是例如下午4:45。 Uiautomator将点击右键。

 clickByText("4");
 clickByText("4");
 clickByText("5");
 clickByText("PM");
 clickByText("OK");

private void clickByText(String text) throws UiObjectNotFoundException {
            UiObject obj = new UiObject(new UiSelector().text(text));
            obj.click();
    }

以下是第一个“4”点击的日志:

  

07-04 16:54:05.259:I / QueryController(25605):匹配选择器:    UiSelector [TEXT = 4] &lt;&lt; ==&gt;&gt; [android.view.accessibility.AccessibilityNodeInfo@592f1;    boundsInParent:Rect(0,0 - 202,129); boundsInScreen:Rect(56,508 - 258,637); packageName:com.android.deskclock; className: android.widget.Button; text:4 ; contentDescription:null;可检查的:假的;检查:false;可聚焦:真实;专注:虚假;   选中:false; clickable:true; longClickable:false;启用:true;   密码:false;可滚动的:false; [ACTION_FOCUS,ACTION_SELECT,   ACTION_CLEAR_SELECTION,ACTION_CLICK,ACTION_ACCESSIBILITY_FOCUS,   ACTION_NEXT_AT_MOVEMENT_GRANULARITY,   ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY]

以下是第二次“4”点击的日志:

  

07-04 16:54:07.798:I / QueryController(25605):匹配选择器:    UiSelector [TEXT = 4] &lt;&lt; ==&gt;&gt; [android.view.accessibility.AccessibilityNodeInfo@5bffd;    boundsInParent:Rect(0,0-66,90); boundsInScreen:Rect(191,264 - 257,354); packageName:com.android.deskclock;班级名称:   的 android.widget.TextView; text:4 ; contentDescription:null;可检查的:假的;检查:false;焦点:虚假;专注:虚假;   选中:false;可点击的:false; longClickable:false;启用:   真正;密码:false;可滚动的:false; [ACTION_SELECT,   ACTION_CLEAR_SELECTION,ACTION_ACCESSIBILITY_FOCUS,   ACTION_NEXT_AT_MOVEMENT_GRANULARITY,   ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY]

我们可以看到一个是点击右边的android.widget.Button,第二个点击它寻找android.widget.TextView。

答案 4 :(得分:0)

创建一个UiObject for 3按钮并单击两次。下面是片段

UiObject three = new UiObject(new UiSelector().text("3"));
three.click();
three.click();