7

UiAutomator を使用して、Android の電卓に「33」と入力するための次のスクリプトがあります。ただし、最初の '3' のみが受け入れられ、2 回目のプレスは完全に無視されます。

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の観察に従って、同じ説明の2番目のリクエストに同じ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;
}

...しかし、「[3]の新しいオブジェクトを作成しました」と1回しか表示されないため、毎回同じUiObjectを明確に再利用しているにもかかわらず、機能しませんでした。

次に、Ramiの観察に従って、次のように関数「クリック」を作成して、UiDevice.click()「トリック」を試しました。

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

ただし、これもうまくいきませんでした。最初の「3」のみが表示され、rect:出力場所が同じであるため、両方のクリックが明らかに同じ場所にあるにもかかわらず、2 番目は無視されます。自分のデスクトップ マウスを使用して手動で '3' を 2 回クリックすると、両方の 3 が正常に表示されます。

また、クリックの間に 2 秒を追加しようとしましThread.sleep()たが、それでも「3」が 1 つしか表示されませんでした。

4

5 に答える 5

3

この問題は、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 など) を見つけてクリックするテストを 2 回実行すると、UiObject を見つけて 2 回クリックするテストと同じように失敗します。これは、UIautomator をリセットしても違いがないため、オブジェクト クエリのデータをデバイスに保存する必要があることを意味します。

于 2013-07-11T17:27:30.463 に答える
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] <<==>> [android.view.accessibility.AccessibilityNodeInfo@592f1; boundsInParent: Rect(0, 0 - 202, 129); boundsInScreen: Rect(56, 508 - 258, 637); パッケージ名: com.android.deskclock; クラス名: android.widget.Button; テキスト: 4 ; contentDescription: null; チェック可能: false; チェック済み: false; フォーカス可能: true; 集中: false; 選択: false; クリック可能: true; longClickable: false; 有効: 真; パスワード: 偽; スクロール可能: false; [ACTION_FOCUS, ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_CLICK, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY]]

2 回目の「4」クリックのログは次のとおりです。

07-04 16:54:07.798: I/QueryController(25605): 一致したセレクタ: UiSelector[TEXT=4] <<==>> [android.view.accessibility.AccessibilityNodeInfo@5bffd; boundsInParent: Rect(0, 0 - 66, 90); boundsInScreen: Rect(191, 264 - 257, 354) ; パッケージ名: com.android.deskclock; クラス名: android.widget.TextView; テキスト: 4 ; contentDescription: null; チェック可能: false; チェック済み: false; フォーカス可能: false; 集中: false; 選択: false; クリック可能: false; longClickable: false; 有効: 真; パスワード: 偽; スクロール可能: false; [ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY]]

1 つは右の android.widget.Button をクリックしており、2 番目のクリックは android.widget.TextView を探していることがわかります。

于 2013-07-05T19:36:54.163 に答える