2013-07-01 13 views
5

Ho il seguente script per digitare "33" nella calcolatrice, in Android, usando UiAutomator. Tuttavia, solo il primo '3' è accettato, la seconda stampa è completamente ignorata.Come premere due volte un pulsante con Google UiAutomator?

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

Ho provato ad aggiungere un sonno per 2 secondi dopo il primo scatto, facendo:

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

... ma questo non cambia nulla.

Ho provato anche facendo clic su un pulsante diverso, tra il 2 '3 di, vale a dire:

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

... ma che non ha funzionato neanche.

Idee?

(Nota: utilizzare Android 4.1.2, in un AVD; in esecuzione su Ubuntu Linux 12.04)

Edit, a seguito delle osservazioni di Rami, ho provato la seguente, di riutilizzare lo stesso oggetto UIObject per una seconda richiesta per la stessa descrizione:

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

... ma non ha funzionato, anche se è chiaramente riutilizzare lo stesso UIObject ogni tempo, perché si dice solo 'nuovo oggetto creato per [3]' una volta.

poi ho provato l'UiDevice.click() 'trucco', con la creazione di una funzione di 'click' nel seguente modo, ancora una volta, a seguito delle osservazioni di Rami:

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

Tuttavia, questo non ha funzionato neanche per me : viene visualizzato solo il primo '3' e il secondo viene ignorato, anche se entrambi i clic sono chiaramente nella stessa posizione, poiché le posizioni di output rect: sono identiche. Se faccio doppio clic su "3" manualmente, utilizzando il mio mouse desktop, entrambi i 3 appaiono ok.

Ho anche provato ad aggiungere due secondi Thread.sleep() tra i clic, e ancora solo un singolo '3' apparve per me.

risposta

1

Ho lo stesso problema, si presenta come la sua ricerca di un altro elemento dell'interfaccia utente che hanno lo stesso testo. Sto cercando di automatizzare la creazione di un allarme, ma quando il tempo è alle 16:45. Uiautomator farà clic sul pulsante destro.

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

Ecco il registro per la prima "4" click:

07-04 16: 54: 05,259: I/QueryController (25605): Selettore Matched: UiSelector [ TEXT = 4] < < == >> [[email protected]; boundsInParent: Rect (0, 0 - 202, 129); boundsInScreen: Rect (56, 508 - 258, 637); packageName: com.android.deskclock; className: android.widget.Pulsante; testo: 4; contentDescription: null; controllabile: falso; controllato: falso; focalizzabile: vero; focalizzato: falso; selezionato: falso; cliccabile: vero; longClickable: false; abilitato: vero; password: falso; scorrevole: falso; [ACTION_FOCUS, ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_CLICK, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY]]

Ecco il registro per la seconda "4" click:

07-04 16: 54: 07.798: I/QueryController (25605): selettore corrispondente: UiSelector [TEXT = 4] < < == >> [android.view.accessibility.Access ibilityNodeInfo @ 5bffd; boundsInParent: Rect (0, 0 - 66, 90); boundsInScreen: Rect (191, 264 - 257, 354); packageName: com.android.deskclock; className: android.widget.TextView; testo: 4; contentDescription: null; controllabile: falso; controllato: falso; focalizzabile: falso; focalizzato: falso; selezionato: falso; cliccabile: falso; longClickable: false; abilitato: true; password: falso; scorrevole: falso; [ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY]]

Possiamo vedere che uno è quello di cliccare il diritto android.widget.Button e il secondo clic la sua ricerca di android.widget.TextView.

2

Ho trovato un piccolo trucco per aggirare il problema per ora. ottenere i limiti ogni volta che si esegue il test in modo che non sia centrato sul dispositivo e si adatti al volo.

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

    Rect four = obj1.getBounds(); 

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

Questo suona come una grande soluzione, ma ho provato solo ora, e non funziona per me. Se faccio doppio clic sul pulsante "3" manualmente due volte, vedo "33", ma se ottengo UiAutomator per usare 'getUiDevice(). Click()' per fare clic due volte nella stessa posizione, quindi vedo ancora solo una singola ' 3' . Questo, anche io aggiungo un 'Thread.sleep (2000)' tra i due clic. –

+0

Ho creato un metodo chiamato 'setUpDigit()' dove ho impostato il mio UIobject 'UiObject zero = new UiObject (nuovo UiSelector(). Text (" 0 "));' e ho un valore globale Rzero che è impostato in lo stesso metodo setUpDigit() 'Rzero = zero.getBounds();' Allora ho un interruttore che userà il valore globale Rzero e clicchiamo con il tasto destro 'getUiDevice(). click (Rzero.centerX(), Rzero.centerY()); 'La parte difficile è quando chiamare setUpDigit(). Deve essere chiamato quando si ha la calcolatrice o per me la creazione di un allarme sullo schermo. –

4

Invece di cercare solo per testo, provare a cercare in base al testo e alla classe. Ecco un metodo di esempio per farlo.

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

E poi se si sta cercando di chiamare questo metodo per il pulsante Calcolatrice con il numero 3 su di esso:

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

È possibile utilizzare lo strumento UiAutomatorViewer: {android-sdk}/strumenti/uiautomator .bat per controllare i nomi di classe e altri attributi di UiObject diversi.

Questo funziona sui miei dispositivi 4.2.2, ma sto scaricando 4.1.2 per testarlo anche lì.

Ho provato su un AVD 4.1.2 e funziona sul mio computer Windows.

2

Questo problema sembra essere costruito nel modo in cui UiObject è impostato. Per quanto posso dire, un'istanza di UiObject non sembra riferirsi a un oggetto specifico sullo schermo. È più simile a un'istanza di ciò che viene indicato da UiSelector quando è stato definito l'oggetto UiObject. La chiave qui è che ogni volta che l'oggetto viene chiamato, cerca un nuovo elemento che soddisfi i requisiti di UiSelector.

Evidence:

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 

Pertanto, penso soluzione di Rami potrebbe effettivamente dal modo corretto di farlo (memorizzare la posizione dell'oggetto attraverso le sue coordinate e cliccare sul centro di quella posizione). Nota importante sulla soluzione alternativa di Rami, salvare le coordinate/rettangolo una volta e quindi riutilizzare le coordinate/rettangolo ogni volta che si desidera fare riferimento all'oggetto. L'uso di obj.getBounds() più volte sullo stesso oggetto non sembra funzionare.

Inoltre, i record degli elementi che sono già stati passati durante l'istanza di UiObject sembrano essere memorizzati nell'app. Eseguendo un test due volte che trova un UiObject (ad esempio il pulsante 4 nella pagina degli allarmi impostata) e fa clic, fallisce allo stesso modo di un test che trova un UiObject e fa clic due volte. Ciò significa che i dati delle query oggetto devono essere memorizzati sul dispositivo poiché il ripristino di UIautomator non fa alcuna differenza.

0

Creare un UIObject per 3 pulsante e fare clic twice.below è il frammento di

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