Guida di riferimento per gli script Robo

Questo documento fornisce informazioni di riferimento sugli script Robo, tra cui struttura, funzionalità, utilizzo, registrazione e azioni. Gli script Robo sono test che automatizzano le attività manuali di garanzia di qualità (QA) per le app mobile e consentono strategie di integrazione continua (CI) e test pre-lancio. Uno script Robo è un file JSON che descrive una sequenza di azioni dell'interfaccia utente (UI) e altre azioni.

Puoi creare uno script Robo nei seguenti modi:

  • Utilizza la funzionalità di registrazione degli script Robo. (Solo Android)

  • Crea lo script Robo manualmente. (Android e iOS+)

  • Registra lo script Robo e poi modificalo manualmente. (Solo Android)

Per scoprire di più sull'utilizzo degli script Robo, consulta Esegui uno script Robo.

Introduzione

Lo script Robo viene fornito al test Robo insieme ad altri input, come l'Android Application Package (APK) dell'app sottoposta a test.

Di seguito è riportato un esempio di script Robo che consente a un utente di accedere a un'app, attivato all'avvio dell'app in fase di test:

[
  {
    "crawlStage": "crawl",
    "contextDescriptor": {
      "condition": "app_under_test_shown"
    },
    "actions": [
      {
        "eventType": "VIEW_TEXT_CHANGED",
        "replacementText": "user123",
        "elementDescriptors": [
          {
            "resourceId": "my.app.package:id/username"
          }
        ]
      },
      {
        "eventType": "VIEW_TEXT_CHANGED",
        "replacementText": "12345",
        "elementDescriptors": [
          {
            "resourceId": "my.app.package:id/password"
          }
        ]
      },
      {
        "eventType": "VIEW_CLICKED",
        "elementDescriptors": [
          {
            "resourceId": "my.app.package:id/login"
          }
        ]
      }
    ]
  }
]

Se in un file è presente un singolo script Robo con la condizione di attivazione predefinita app_under_test_shown, come nell'esempio precedente, puoi specificare lo script Robo in un file utilizzando un formato più semplice, ovvero come una sequenza delle sue azioni:

[
  {
    "eventType": "VIEW_TEXT_CHANGED",
    "replacementText": "user123",
    "elementDescriptors": [
      {
        "resourceId": "my.app.package:id/username"
      }
    ]
  },
  {
    "eventType": "VIEW_TEXT_CHANGED",
    "replacementText": "12345",
    "elementDescriptors": [
      {
        "resourceId": "my.app.package:id/password"
      }
    ]
  },
  {
    "eventType": "VIEW_CLICKED",
    "elementDescriptors": [
      {
        "resourceId": "my.app.package:id/login"
      }
    ]
  }
]

Supporto di iOS+ per gli script Robo

Robo per iOS+ (beta) offre un supporto limitato per gli script di Robo. La sintassi degli script Robo per iOS+ è identica a quella di Android e le funzionalità iOS+ supportate si comportano in modo simile alle loro controparti Android.

Le seguenti azioni sono supportate in iOS+:

  • Asserzione
  • Fai clic su
  • Clic lungo
  • Scorri
  • Ignora tutti gli elementi
  • Attendi
  • Acquisisci screenshot
  • Termina scansione

In iOS+ sono supportati i seguenti attributi identificativi nei descrittori degli elementi:

  • Nome corso
  • Nome classe predecessore
  • Descrizione dei contenuti (ed espressione regolare)
  • Testo (e regex)

In iOS+ sono supportate le seguenti condizioni di attivazione nei descrittori di contesto:

  • App in fase di test mostrata
  • Elemento presente
  • Azione dello script non Robo eseguita

Struttura

Uno script Robo ha diversi attributi che descrivono il modo in cui Robo lo esegue. La maggior parte di questi attributi è facoltativa e ha valori predefiniti:

Attributo Descrizione
id Un numero intero che aiuta a monitorare questo script Robo negli output di scansione. Robo ha script Robo integrati con i propri id. Anche se lo stesso id in script Robo diversi non influisce sul loro comportamento, distinguere le azioni di questi script Robo negli output di scansione può essere difficile. Ti consigliamo di assegnare un id univoco di 1000 o superiore per i tuoi script Robo per evitare conflitti.
description Simile a id, ma più descrittivo.
crawlStage La fase di una scansione in cui Robo applica questo script Robo. Per impostazione predefinita, è la fase di scansione principale.
priority La priorità di questo script Robo rispetto ad altri script Robo. Per impostazione predefinita, tutti gli script Robo hanno una priorità pari a 1.
maxNumberOfRuns Specifica quante volte durante una scansione Robo può eseguire questo script Robo. Per impostazione predefinita, Robo può eseguire uno script Robo una volta.
contextDescriptor Descrive il contesto o la condizione che attiva questo script Robo. Se omessa, la condizione di attivazione di questo script Robo viene considerata sempre soddisfatta; in altre parole, lo script Robo è incondizionato.
actions Tutte le azioni di questo script Robo.

Un singolo file contiene una raccolta di uno o più script Robo.

Di seguito è riportato un esempio di file con due script Robo incondizionati, ciascuno con una singola azione eseguita una volta all'inizio di una scansione:

[
  {
    "id": 1000,
    "description": "My first Robo script",
    "actions": [
      {
        "eventType": "DISABLE_KEYBOARD"
      }
    ]
  },
  {
    "id": 1001,
    "description": "My second Robo script",
    "actions": [
      {
        "eventType": "PRESSED_BACK"
      }
    ]
  }
]

Descrittore del contesto

Un descrittore di contesto definisce il contesto o la condizione che attiva uno script Robo utilizzando uno o una combinazione di più attributi:

Attributo Descrizione
"condition": "always" Attiva sempre uno script Robo.
"condition": "element_present" Verifica che sullo schermo sia presente un widget dell'interfaccia utente corrispondente a elementDescriptors o al testo specificato da visionText.
"condition": "element_disabled" Verifica che un widget UI corrispondente a elementDescriptors sia presente sullo schermo e che non sia possibile interagirvi.
"condition": "element_checked" Verifica che un widget della UI corrispondente a elementDescriptors sia presente sullo schermo e sia selezionato.
"condition": "app_under_test_shown" Verifica che l'app in fase di test sia in esecuzione in primo piano.
"condition": "default_launcher_shown" Verifica che venga visualizzata la schermata Home di un dispositivo, il che significa che non sono in esecuzione app in primo piano.
"condition": "non_roboscript_action_performed" Controlla che le ultime nonRoboscriptActionCount azioni consecutive eseguite dal test Robo non siano azioni dello script Robo.
negateCondition Se impostato su true, nega condition. Ad esempio, puoi utilizzare questo attributo per verificare se un widget UI NON è presente sullo schermo o se l'app in fase di test NON è in esecuzione in primo piano.
elementDescriptors Uno o più descrittori di elementi che identificano un widget UI sullo schermo. Viene utilizzato in combinazione con le condizioni element_present, element_disabled e element_checked. Si esclude a vicenda con visionText. Per saperne di più, consulta Descrittori degli elementi.
visionText Il testo sullo schermo viene rilevato utilizzando l'API Optical Character Recognition (OCR). visionText viene utilizzato in combinazione con la condizione element_present. Si esclude a vicenda con elementDescriptors.
nonRoboscriptActionCount Il numero di azioni consecutive non dello script Robo eseguite in precedenza. Viene utilizzato in combinazione con la condizione non_roboscript_action_performed per attivare uno script Robo dopo ogni nonRoboscriptActionCount azione Robo. Il valore predefinito è 1.

Di seguito è riportato un esempio di script Robo attivato da un widget UI con un ID risorsa "my.app.package:id/page_header" presente sullo schermo:

{
  "id": 1000,
  "contextDescriptor": {
    "condition": "element_present",
    "elementDescriptors": [
      {
        "resourceId": "my.app.package:id/page_header"
      }
    ]
  },
  "actions": [
    {
      "eventType": "VIEW_CLICKED",
      "elementDescriptors": [
        {
          "text": "Settings"
        }
      ]
    }
  ]
}

Di seguito è riportato un esempio di script Robo attivato da "Privacy Policy" rilevato dal riconoscimento ottico dei caratteri (OCR):

{
  "id": 1000,
  "description": "Vision text Robo script",
  "contextDescriptor": {
    "condition": "element_present",
    "visionText": "Privacy Policy"
  },
  "actions": [
    {
      "eventType": "VIEW_CLICKED",
      "visionText": "Privacy Policy"
    }
  ]
}

Di seguito è riportato un esempio di script Robo che attende 5 secondi dopo ogni azione Robo non di script:

{
  "contextDescriptor": {
    "condition": "non_roboscript_action_performed"
  },
  "maxNumberOfRuns" : 1000,
  "actions" : [
    {
      "eventType" : "WAIT",
      "delayTime" : 5000
    }]
}

Azioni

Ogni azione in uno script Robo è rappresentata come un bundle di una o più coppie attributo-valore, descritte nella tabella seguente:

Attributo Descrizione
eventType Specifica il tipo di azione, ad esempio clic, modifica del testo e così via. Obbligatorio per ogni azione.
elementDescriptors Descrittori che identificano un widget della UI. Obbligatorio per tutte le azioni che hanno un widget UI di destinazione, ad esempio il clic su un determinato pulsante.
optional Se impostata su true, questa azione viene ignorata quando non può essere eseguita. Ad esempio, questa azione viene ignorata quando non riesce a trovare il widget UI di destinazione su uno schermo, senza che lo script Robo contenente non vada a buon fine. Per impostazione predefinita, il valore è false.
replacementText Il testo da inserire nel widget dell'interfaccia utente di destinazione. Obbligatorio per le azioni di modifica del testo.
swipeDirection Specifica la direzione dello scorrimento. Obbligatorio per le azioni di scorrimento.
delayTime Specifica il tempo di attesa in millisecondi. Obbligatorio per le azioni di attesa.
pointTapXCoordinate e pointTapYCoordinate Le coordinate X e Y dei pixel del punto toccato. Si esclude a vicenda con pointTapXPercent e pointTapYPercent. Obbligatorio per le azioni di tocco di un punto.
pointTapXPercent e pointTapYPercent Le coordinate X e Y in percentuale del punto toccato. Si esclude a vicenda con pointTapXCoordinate e pointTapYCoordinate. Obbligatorio per le azioni di tocco di un punto.

Di seguito è riportato un esempio di script Robo con due azioni senza widget UI di destinazione, il che significa che queste azioni non operano su un widget UI specifico:

[
  {
    "eventType": "WAIT",
    "delayTime": 3000
  },
  {
    "eventType": "PRESSED_BACK"
  }
]

Descrittori degli elementi

Un descrittore di elementi identifica un widget UI utilizzando uno o più dei seguenti attributi di identificazione:

Attributo Descrizione
className –
ancestorClassName Nome della classe dell'antenato della gerarchia della UI dell'elemento. Un predecessore è uno qualsiasi dei nodi principali nella gerarchia dell'interfaccia utente dell'elemento, incluso l'elemento stesso.
resourceId –
resourceIdRegex Espressione regolare Java per trovare corrispondenze con resourceId.
contentDescription –
contentDescriptionRegex Espressione regolare Java per trovare corrispondenze con contentDescription.
text (visualizzato sullo schermo) –
textRegex Espressione regolare Java per trovare una corrispondenza con text.
groupViewChildPosition, recyclerViewChildPosition o adapterViewChildPosition Rappresenta la posizione secondaria di un widget UI a seconda del tipo di widget principale.

Spesso questi attributi non sono definiti, ad esempio un pulsante potrebbe non avere testo e descrizione dei contenuti. Anche se sono presenti alcuni valori degli attributi, potrebbero non essere univoci in una determinata schermata dell'app (incluso resourceId).

Ad esempio, la differenziazione tra gli elementi di un elenco è comunemente possibile solo utilizzando le diverse posizioni secondarie all'interno del widget principale. Ciò significa che l'utilizzo di un solo descrittore di elementi per identificare un widget UI di solito non è sufficiente. Pertanto, l'attributo elementDescriptors di un'azione contiene una sequenza di descrittori di elementi ordinati in modo che il primo corrisponda al widget UI di destinazione, il secondo al widget principale del widget UI di destinazione e così via. Il widget UI di destinazione di un'azione viene abbinato quando tutti i relativi descrittori di elementi corrispondono alla sottogerarchia del widget UI corrispondente.

Di seguito è riportato un esempio di script Robo con azioni di modifica del testo e di clic, entrambe le quali richiedono l'identificazione del widget UI di destinazione utilizzando i descrittori degli elementi forniti:

[
  {
    "eventType": "VIEW_TEXT_CHANGED",
    "replacementText": "John",
    "elementDescriptors": [
      {
        "className": "android.support.v7.widget.AppCompatEditText",
        "groupViewChildPosition": 0,
        "resourceId": "com.google.samples.apps.topeka:id/first_name"
      },
      {
        "className": "android.widget.FrameLayout",
        "groupViewChildPosition": 0
      },
      {
        "className": "android.support.design.widget.TextInputLayout",
        "groupViewChildPosition": 1
      }
    ]
  },
  {
    "eventType": "VIEW_CLICKED",
    "elementDescriptors": [
      {
        "className": "android.support.design.widget.FloatingActionButton",
        "groupViewChildPosition": 1,
        "resourceId": "com.google.samples.apps.topeka:id/done"
      },
      {
        "className": "android.widget.FrameLayout",
        "groupViewChildPosition": 1,
        "resourceId": "com.google.samples.apps.topeka:id/content"
      },
      {
        "className": "android.widget.FrameLayout",
        "groupViewChildPosition": 0,
        "resourceId": "com.google.samples.apps.topeka:id/sign_in_content"
      }
    ]
  }
]

Opzioni di esecuzione

Se vuoi, puoi anteporre all'elenco di azioni in uno script Robo un oggetto JSON che specifica le opzioni di esecuzione per lo script Robo. Questa intestazione di configurazione inizia con la parola chiave roboscript seguita da una rappresentazione JSON delle opzioni di esecuzione desiderate.

Gli script Robo supportano le seguenti opzioni di esecuzione:

  • executionMode: opzioni di esecuzione applicate durante l'esecuzione di uno script Robo:
    • strict: se impostato su true, lo script Robo non utilizza corrispondenza parziale, salto dell'azione corrente e sospensione. In altre parole, lo script Robo viene eseguito come un normale test di instrumentazione e non va a buon fine non appena una delle sue azioni non può essere eseguita. Per impostazione predefinita, è false.
    • dismiss_popups: se impostato su true, il test Robo ignora eventuali finestre di dialogo impreviste durante l'esecuzione dello script Robo anche in modalità strict. Questa opzione non ha effetto se non è attiva la modalità strict. Il valore predefinito è false.
    • notify: se impostato su false, lo script Robo non mostra notifiche sullo schermo all'inizio e alla fine della sua esecuzione. Per impostazione predefinita, è true.
  • postscript: opzioni di esecuzione applicate dopo il completamento di uno script Robo:
    • terminate: se impostato su true, il test Robo interrompe la scansione dopo il completamento dello script Robo. Il valore predefinito è false.

Di seguito è riportato un esempio di script Robo eseguito in modalità strict senza notifiche sullo schermo che attende tre secondi, dopodiché la scansione si interrompe:

"roboscript": {
  "executionMode": {
    "strict": true,
    "notify": false
  },
  "postscript": {
    "terminate": true
  }
}
[
  {
    "eventType": "WAIT",
    "delayTime": 3000
  }
]

Parametri del modello

Un parametro del modello è un segnaposto in uno script Robo che viene sostituito con il valore effettivo quando il test Robo carica lo script Robo per l'esecuzione. I parametri del modello sono preceduti da un doppio trattino basso seguito da un segno di percentuale e sono seguiti da un segno di percentuale seguito da un doppio trattino basso.

Gli script robot supportano il seguente parametro del template:

  • __%APP_PACKAGE_NAME%__: il nome del pacchetto dell'app sottoposta a test.

Di seguito è riportato un esempio di script Robo che interrompe il processo dell'app sottoposta a test:

[
  {
    "eventType": "ADB_SHELL_COMMAND",
    "command": "am force-stop __%APP_PACKAGE_NAME%__"
  }
]

Commenti

Uno script Robo può contenere righe di commento, ovvero righe che iniziano con # o //.

Di seguito è riportato un esempio di script Robo con un paio di commenti:

# Confirm a user account.
[
  {
    // Click the DONE button.
    "eventType": "VIEW_CLICKED",
    "elementDescriptors": [
      {
        "resourceId": "com.google.samples.apps.topeka:id/done"
      }
    ]
  }
]

Funzionalità

Per impostazione predefinita, lo script Robo rimane attivo finché non vengono completate (o almeno tentate) tutte le azioni dello script. Il test Robo continua a cercare di trovare una corrispondenza con un'azione dello script Robo ogni volta che sceglie un'azione da eseguire. Lo script Robo utilizza le seguenti tecniche per aumentare la robustezza:

Tecnica Descrizione
Corrispondenza parziale Se l'azione dello script Robo corrente non può essere abbinata completamente, i criteri di corrispondenza vengono allentati e l'abbinamento viene riprovato. La corrispondenza parziale non considera il descrittore dell'elemento più esterno durante la corrispondenza del widget UI di destinazione di un'azione dello script Robo.

Se la corrispondenza parziale ha esito positivo, l'azione dello script Robo corrispondente viene eseguita come di consueto. Questa tecnica supporta scenari in cui la struttura dell'app cambia, ad esempio tra le versioni dell'app, quando gli elementi dello schermo vengono riorganizzati.

Salta l'azione corrente Se l'azione dello script Robo corrente non può essere abbinata completamente o parzialmente, Robo tenta di abbinare l'azione dello script Robo successiva. Se l'azione successiva corrisponde completamente o parzialmente, il test Robo salta l'azione dello script Robo corrente (e non vi torna mai) ed esegue quella successiva.

Questa tecnica supporta scenari in cui il comportamento dell'app cambia tra le versioni o è instabile, ad esempio quando una finestra di dialogo intermittente potrebbe apparire in schermate diverse durante la registrazione rispetto alla riproduzione di uno script Robo.

Sospendi Se non è possibile trovare una corrispondenza completa o parziale per le azioni dello script Robo attuali o successive, lo script Robo viene temporaneamente sospeso e il test Robo sceglie un'azione da eseguire utilizzando le altre strategie. Una volta completata questa azione, il test Robo riprende l'esecuzione dello script Robo.

Finché non è possibile trovare una corrispondenza per le azioni dello script Robo correnti o successive, lo script Robo rimane sospeso per un numero qualsiasi di azioni. Pertanto, gli script Robo non devono necessariamente essere un prologo per un test Robo e puoi alternare le azioni dello script Robo con le azioni standard del test Robo. Questa tecnica supporta scenari in cui il comportamento dell'app è instabile o quando le modifiche tra le versioni dell'app sono abbastanza grandi da richiedere che il test Robo "colmi le lacune" con le sue azioni standard.

Priorità

Se uno script Robo raggiunge il suo maxNumberOfRuns, non può più essere attivato in una determinata scansione. Se il contesto corrente può attivare più di uno script Robo, la priorità viene assegnata scegliendo, nell'ordine seguente, lo script Robo che:

  1. Ha un attributo contextDescriptor.
  2. Ha la priority più alta (per impostazione predefinita, tutti gli script Robo hanno la stessa priority di esecuzione di 1).
  3. Viene visualizzato per primo nell'elenco degli script Robo, se le priorità degli script Robo sono le stesse.

Di seguito è riportato un esempio di file con tre script Robo che eseguono la stessa azione e vengono attivati dalla stessa condizione, ovvero l'app in fase di test in primo piano:

[
  {
    "id": 1000,
    "description": "Robo script 1",
    "contextDescriptor": {
      "condition": "app_under_test_shown"
    },
    "actions": [
      {
        "eventType": "WAIT",
        "delayTime": 3000
      }
    ]
  },
  {
    "id": 1001,
    "description": "Robo script 2",
    "priority": "2",
    "contextDescriptor": {
      "condition": "app_under_test_shown"
    },
    "actions": [
      {
        "eventType": "WAIT",
        "delayTime": 3000
      }
    ]
  },
  {
    "id": 1002,
    "description": "Robo script 3",
    "contextDescriptor": {
      "condition": "app_under_test_shown"
    },
    "actions": [
      {
        "eventType": "WAIT",
        "delayTime": 3000
      }
    ]
  }
]

Quando l'app in fase di test è in primo piano, Robo attiva quanto segue, in ordine:

  1. "Robo script 2" perché ha la priorità più alta.
  2. "Robo script 1" perché appare prima tra gli script Robo applicabili rimanenti con la stessa priorità.
  3. "Robo script 3" come ultimo script Robo applicabile.

Esecuzioni ripetute

Per impostazione predefinita, Robo attiva uno script Robo al massimo una volta durante una scansione. Questo valore può essere modificato tramite l'attributo maxNumberOfRuns.

Di seguito è riportato un esempio di script Robo che porta l'app in fase di test in background fino a 10 volte:

{
  "id": 1000,
  "maxNumberOfRuns": 10,
  "contextDescriptor": {
    "condition": "app_under_test_shown"
  },
  "actions": [
    {
      "eventType": "GO_HOME"
    }
  ]
}

Fase di scansione

Gli script Robo sono applicabili in diverse fasi di una determinata scansione Robo:

Fase di scansione Descrizione
pre_crawl Prima che Robo venga avviato e inizi la scansione dell'app in fase di test.
post_crawl Dopo che Robo ha completato la scansione dell'app in fase di test. Uno script Robo post_crawl non deve superare i 15 secondi di durata, altrimenti la scansione potrebbe terminare con un timeout.
crawl La fase di scansione principale, in cui Robo esegue la scansione dell'app in fase di test.
close_screen Quando Robo tenta di tornare indietro (backtrack) da una determinata schermata, dopo aver esplorato tutte le azioni possibili su questa schermata. Per impostazione predefinita, Robo preme il pulsante Indietro, il che non è auspicabile in alcuni scenari.

Se l'attributo crawlStage di uno script Robo non è specificato, viene considerato crawl.

Di seguito è riportato un esempio di script Robo che cancella i dati utente dell'app sottoposta a test prima che Robo inizi la scansione:

{
  "id": 1000,
  "crawlStage": "pre_crawl",
  "actions": [
    {
      "eventType": "ADB_SHELL_COMMAND",
      "command": "pm clear __%APP_PACKAGE_NAME%__"
    }
  ]
}

Di seguito è riportato un esempio di script Robo che indica a Robo di fare clic su "Cancel" ogni volta che tenta di tornare indietro (backtrack) da una finestra di dialogo di conferma:

{
  "id": 1000,
  "crawlStage": "close_screen",
  "maxNumberOfRuns": 999,
  "contextDescriptor": {
    "condition": "element_present",
    "elementDescriptors": [
      {
        "resourceId": "my.app.package:id/confirmation_dialog"
      }
    ]
  },
  "actions": [
    {
      "eventType": "VIEW_CLICKED",
      "elementDescriptors": [
        {
          "text": "Cancel"
        }
      ]
    }
  ]
}

Azioni condizionali

Uno script Robo può contenere azioni condizionali. Le azioni condizionali hanno tre attributi aggiuntivi che descrivono il modo in cui Robo le esegue:

Attributo Descrizione
priority La priorità di questa azione condizionale rispetto ad altre azioni condizionali all'interno dello script Robo che la contiene. Per impostazione predefinita, tutte le azioni condizionali hanno una priorità pari a 1.
maxNumberOfRuns Il numero di volte in cui questa azione condizionale può essere eseguita durante una singola esecuzione dello script Robo che la contiene. Per impostazione predefinita, tutte le azioni condizionali possono essere eseguite al massimo una volta in una singola esecuzione dello script Robo che le contiene.
contextDescriptor Il contesto o la condizione che attiva questa azione condizionale. Ha la stessa struttura e offre funzionalità simili a quelle del contextDescriptor dello script robot.

Quando viene attivato, uno script Robo esegue le azioni non condizionali una per una in ordine di visualizzazione. Se uno script Robo contiene azioni condizionali, queste vengono prese in considerazione ogni volta prima di scegliere un'azione non condizionale da eseguire. Se un'azione condizionale viene attivata e selezionata in base alla sua priorità e al numero rimanente di esecuzioni, lo script Robo esegue questa azione condizionale. In caso contrario, lo script Robo esegue la seguente azione non condizionale. Per essere valido, uno script Robo deve contenere almeno un'azione non condizionale.

Di seguito è riportato un esempio di script Robo incondizionato con un'azione condizionale che chiude le finestre di dialogo popup se vengono visualizzate in qualsiasi momento durante l'esecuzione dello script Robo:

{
  "id": 1000,
  "actions": [
    {
      "description": "Dismiss popup",
      "maxNumberOfRuns": 100,
      "contextDescriptor": {
        "condition": "default_launcher_shown",
        "negateCondition": true
      },
      "eventType": "GO_HOME"
    },
    {
      "description": "Screen off",
      "eventType": "ADB_SHELL_COMMAND",
      "command": "input keyevent 26"
    },
    {
      "description": "Wait for 10 seconds",
      "eventType": "WAIT",
      "delayTime": 10000
    },
    {
      "description": "Screen on",
      "eventType": "ADB_SHELL_COMMAND",
      "command": "input keyevent 82"
    },
    {
      "description": "Wait for 10 seconds",
      "eventType": "WAIT",
      "delayTime": 10000
    }
}

Ignorare le azioni

Uno script Robo può contenere istruzioni per Robo per ignorare widget UI specifici o tutti i widget UI su una determinata schermata. Queste istruzioni sono rappresentate come "azioni" di ignoramento con eventType ELEMENT_IGNORED e ALL_ELEMENTS_IGNORED corrispondentemente.

Ogni volta che l'attributo contextDescriptor di uno script Robo contenente azioni di ignoramento corrisponde a una determinata schermata, Robo non interagisce con i widget UI scelti come target dalle azioni di ignoramento (a meno che un'altra azione dello script Robo non faccia eseguire a Robo un'azione su uno dei widget UI ignorati).

Uno script Robo può contenere un mix di azioni ignorate, condizionali e non condizionali. A differenza di altre azioni degli script Robo, le azioni di ignoramento vengono applicate finché l'elemento contextDescriptor dello script Robo che le contiene corrisponde a una schermata durante una scansione Robo, indipendentemente dai valori degli attributi priority e maxNumberOfRuns.

Di seguito è riportato un esempio di file con due script Robo. Il primo script Robo fa sì che Robo ignori tutti i widget UI su una schermata contenente un widget UI con un ID risorsa "my.app.package:id/ignored_screen". Il secondo script Robo fa sì che Robo ignori i widget UI i cui ID risorsa corrispondono alla regex Java ".*:id/done" su una schermata contenente un widget UI con un ID risorsa "my.app.package:id/main_screen":

[
  {
    "id": 1000,
    "contextDescriptor": {
      "condition": "element_present",
      "elementDescriptors": [
        {
          "resourceId": "my.app.package:id/ignored_screen"
        }
      ]
    },
    "actions": [
      {
        "eventType": "ALL_ELEMENTS_IGNORED"
      }
    ]
  },
  {
    "id": 1001,
    "contextDescriptor": {
      "condition": "element_present",
      "elementDescriptors": [
        {
          "resourceId": "my.app.package:id/main_screen"
        }
      ]
    },
    "actions": [
      {
        "eventType": "ELEMENT_IGNORED",
        "elementDescriptors": [
          {
            "resourceIdRegex": ".*:id/done"
          }
        ]
      }
    ]
  }
]

Supporto di RecyclerView e AdapterView

Gli elementi secondari dei widget RecyclerView e AdapterView vengono caricati dinamicamente e potrebbero essere visualizzati a molti scorrimenti di distanza dalla schermata corrente. Poiché le dimensioni di uno schermo e il numero di scorrimenti necessari per raggiungere questo elemento secondario sono diversi per i vari fattori di forma dei dispositivi, è molto più efficace fare affidamento sulla posizione dei dati dell'elemento secondario, che è assoluta. È un approccio meno efficace fare affidamento sul numero di scorrimenti necessari per portare questo elemento secondario sullo schermo e poi utilizzare la sua posizione sullo schermo.

Pertanto, lo script Robo acquisisce le posizioni assolute dei dati degli elementi secondari di RecyclerView che sono i target delle azioni dello script Robo come recyclerViewChildPosition. Lo script Robo acquisisce anche le posizioni assolute dei dati degli elementi secondari di AdapterView che sono i target delle azioni dello script Robo come adapterViewChildPosition.

Le azioni sugli elementi secondari di RecyclerView e AdapterView vengono eseguite nei seguenti passaggi:

  1. Il test Robo garantisce che l'elemento secondario corrispondente venga visualizzato sullo schermo tramite un'azione di posizionamento sul RecyclerView o AdapterView che lo contiene.

  2. Il test Robo esegue l'azione registrata direttamente sull'elemento secondario, poiché è già visualizzato sullo schermo.

Di seguito è riportato un esempio di azione di clic su un elemento secondario di AdapterView (android.widget.GridView):

{
  "eventType": "VIEW_CLICKED",
  "elementDescriptors": [
    {
      "className": "com.google.samples.apps.topeka.widget.AvatarView",
      "adapterViewChildPosition": 5,
      "resourceId": "com.google.samples.apps.topeka:id/avatar",
      "contentDescription": "Avatar 6"
    },
    {
      "className": "android.widget.GridView",
      "groupViewChildPosition": 1,
      "resourceId": "com.google.samples.apps.topeka:id/avatars"
    },
    {
      "className": "android.widget.LinearLayout",
      "groupViewChildPosition": 1
    },
    {
      "className": "android.widget.LinearLayout",
      "groupViewChildPosition": 0
    }
  ]
}

Di seguito è riportato un esempio di azione di clic su un elemento secondario di RecyclerView (android.support.v7.widget.RecyclerView):

{
  "eventType": "VIEW_CLICKED",
  "elementDescriptors": [
    {
      "className": "android.support.v7.widget.AppCompatTextView",
      "groupViewChildPosition": 1,
      "resourceId": "com.google.samples.apps.topeka:id/category_title"
    },
    {
      "className": "android.widget.FrameLayout",
      "recyclerViewChildPosition": 8,
      "resourceId": "com.google.samples.apps.topeka:id/category_item"
    },
    {
      "className": "android.support.v7.widget.RecyclerView",
      "groupViewChildPosition": 1,
      "resourceId": "com.google.samples.apps.topeka:id/categories"
    },
    {
      "className": "android.widget.FrameLayout",
      "groupViewChildPosition": 1,
      "resourceId": "com.google.samples.apps.topeka:id/category_container"
    },
    {
      "className": "android.widget.LinearLayout",
      "groupViewChildPosition": 0
    }
  ]
}

Registra uno script Robo in Android Studio ed eseguilo in Test Lab

Puoi creare uno script Robo in Android Studio, che lo salva come file JSON. Puoi quindi caricare il file JSON su Firebase Test Lab con l'applicazione ed eseguire il test di conseguenza.

Quando esegui un test Robo con uno script allegato, il test Robo esegue prima le azioni pre-scritte e poi esplora l'app come di consueto.

Per creare un file JSON di script Robo in Android Studio, segui i passaggi descritti in Registra uno script Robo utilizzando Test Lab in Android Studio.

Azioni degli script Robo

Il seguente attributo facoltativo comune si applica a tutte le azioni:

  • description: consente di monitorare l'esecuzione di questa azione dello script Robo negli output del test Robo.

Asserzione

Se la condizione dichiarata è vera, lo script Robo continua con l'azione successiva, che potrebbe essere un'altra asserzione. In caso contrario, l'esecuzione dello script Robo viene interrotta a causa di un'asserzione non riuscita.

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "ASSERTION" --
contextDescriptor Descrive il contesto o la condizione dichiarati. Ha la stessa struttura e offre funzionalità simili a contextDescriptor dello script robot.

Di seguito è riportato un esempio di asserzione di uno script Robo che verifica che l'app in fase di test sia in primo piano:

{
  "eventType": "ASSERTION",
  "contextDescriptor": {
    "condition": "app_under_test_shown"
  }
}

Di seguito è riportato un esempio di asserzione di uno script Robo che verifica che un widget dell'interfaccia utente con l'ID risorsa "com.google.samples.apps.topeka:id/done" sia presente su uno schermo:

{
  "eventType": "ASSERTION",
  "contextDescriptor": {
    "condition": "element_present",
    "elementDescriptors": [
      {
        "resourceId": "com.google.samples.apps.topeka:id/done"
      }
    ]
  }
}

Di seguito è riportato un esempio di asserzione di uno script Robo che verifica che "Settings" NON venga rilevato su uno schermo utilizzando l'OCR:

{
  "eventType": "ASSERTION",
  "contextDescriptor": {
    "condition": "element_present",
    "negateCondition": true,
    "visionText": "Settings"
  }
}

Fai clic su

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
eventType Specifica il tipo di azione dello script Robo.
"eventType": "VIEW_CLICKED" Fa clic sull'elemento di destinazione dell'app in fase di test.
"eventType": "SOFT_KEYBOARD_CLICK" Fai clic sull'elemento target della tastiera su schermo.
"eventType": "SOFT_KEYBOARD_RANDOM_CLICK" Fa clic su elementi casuali della tastiera su schermo fino a maxNumberOfRuns volte.
"eventType": "LIST_ITEM_CLICKED" Utilizzato dal registratore di script Robo in Android Studio per fare clic sugli elementi dell'elenco.
elementDescriptors Identifica il widget dell'interfaccia utente su cui è stato fatto clic utilizzando la gerarchia dell'interfaccia utente di Android. Si esclude a vicenda con visionText.
visionText Identifica l'elemento selezionato utilizzando l'OCR. Si esclude a vicenda con elementDescriptors.
matchIndex Specifica l'indice dell'occorrenza dell'elemento target corrispondente, quando l'elemento target viene identificato utilizzando visionText. Se è 0, l'azione dello script Robo sceglie il primo elemento corrispondente, se è 1, l'azione dello script Robo sceglie il secondo elemento corrispondente e così via. L'ordine è determinato da sinistra a destra, dall'alto verso il basso. Il valore predefinito è 0 (viene scelta la prima corrispondenza).
maxNumberOfRuns Specifica quante volte fare clic su un elemento casuale della tastiera su schermo, quando eventType è SOFT_KEYBOARD_RANDOM_CLICK. Il valore predefinito è 1.

Di seguito è riportato un esempio di azione di uno script Robo che fa clic su un pulsante con l'ID risorsa "com.google.samples.apps.topeka:id/done":

{
  "eventType": "VIEW_CLICKED",
  "elementDescriptors": [
    {
      "resourceId": "com.google.samples.apps.topeka:id/done"
    }
  ]
}

Di seguito è riportato un esempio di azione di uno script Robo che fa clic sulla seconda occorrenza della parola "Search" rilevata su uno schermo utilizzando l'OCR:

{
  "eventType": "VIEW_CLICKED",
  "visionText": "Search",
  "matchIndex": 1
}

Di seguito è riportato un esempio di azione di uno script Robo che fa clic su un elemento della tastiera su schermo con una descrizione dei contenuti "Emoji button":

{
  "eventType": "SOFT_KEYBOARD_CLICK",
  "elementDescriptors": [
    {
      "contentDescription": "Emoji button"
    }
  ]
}

Di seguito è riportato un esempio di azione di uno script Robo che fa clic su elementi casuali della tastiera su schermo fino a cinque volte:

{
  "eventType": "SOFT_KEYBOARD_RANDOM_CLICK",
  "maxNumberOfRuns": 5
}

Disattiva la tastiera su schermo

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "DISABLE_KEYBOARD" --

Di seguito è riportato un esempio di azione di uno script Robo che disattiva la tastiera su schermo:

{
  "eventType": "DISABLE_KEYBOARD"
}

Esegui comando shell adb

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "ADB_SHELL_COMMAND" --
command Il comando della shell Android Debug Bridge (adb) da eseguire.

Il seguente attributo è facoltativo:

  • expectedOutputRegex: l'output previsto del comando come espressione regolare Java. Se l'output non corrisponde, l'azione dello script Robo non va a buon fine. Per impostazione predefinita, è una stringa vuota, il che significa che l'output non viene controllato.

Di seguito è riportato un esempio di azione di uno script Robo che cancella i dati utente dell'app in fase di test:

{
  "eventType": "ADB_SHELL_COMMAND",
  "command": "pm clear __%APP_PACKAGE_NAME%__"
}

Concedi le autorizzazioni

Questa azione viene registrata dal registratore di script Robo in Android Studio per la compatibilità con le versioni precedenti di Espresso Test Recorder. Il test Robo concede tutte le autorizzazioni all'app in fase di test all'inizio di ogni scansione, pertanto questa azione non è operativa. NON utilizzare questa azione negli script Robo.

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "PERMISSIONS_REQUEST" --

Ignora tutti gli elementi su uno schermo

Questa azione fa sì che Robo ignori tutti gli elementi su qualsiasi schermata che attiva lo script Robo contenente.

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "ALL_ELEMENTS_IGNORED" --

Di seguito è riportato un esempio di azione di uno script Robo che fa sì che Robo ignori tutti gli elementi di una schermata:

{
  "eventType": "ALL_ELEMENTS_IGNORED"
}

Ignora un elemento

Questa azione fa sì che Robo ignori uno o più elementi che corrispondono al selettore elementDescriptors specificato.

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "ELEMENT_IGNORED" --
elementDescriptors Identifica i widget della UI ignorati utilizzando la gerarchia della UI di Android.

Il seguente attributo è facoltativo:

  • ignoreChildren: se impostato su true, Robo ignora anche tutti i discendenti dei widget della UI ignorati. Il valore predefinito è false.

Di seguito è riportato un esempio di azione di uno script Robo che fa sì che Robo ignori tutti gli elementi le cui descrizioni dei contenuti iniziano con "Avatar":

{
  "eventType": "ELEMENT_IGNORED",
  "elementDescriptors": [
    {
      "contentDescriptionRegex": "Avatar.*"
    }
  ]
}

Testo di input

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
eventType Specifica il tipo di azione dello script Robo.
"eventType": "VIEW_TEXT_CHANGED" Inserisce il testo specificato nel widget UI di destinazione.
"eventType": "ENTER_TEXT" inserisce il testo specificato nel widget UI di destinazione e poi invia un evento KEYCODE_ENTER a questo widget UI.
elementDescriptors Identifica il widget UI di destinazione utilizzando la gerarchia della UI di Android.
replacementText Il testo da inserire nel widget dell'interfaccia utente di destinazione.

Di seguito è riportato un esempio di azione di uno script Robo che inserisce "John" in un widget della UI con l'ID risorsa "com.google.samples.apps.topeka:id/first_name":

{
  "eventType": "VIEW_TEXT_CHANGED",
  "replacementText": "John",
  "elementDescriptors": [
    {
      "resourceId": "com.google.samples.apps.topeka:id/first_name"
    }
  ]
}

Clic lungo

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "VIEW_LONG_CLICKED" --
elementDescriptors Identifica il widget UI di destinazione utilizzando la gerarchia della UI di Android. Si escludono a vicenda con visionText.
visionText Identifica l'elemento su cui è stato fatto clic con un tocco prolungato utilizzando l'OCR. Si esclude a vicenda con elementDescriptors.
matchIndex Specifica l'indice dell'occorrenza dell'elemento target corrispondente, quando l'elemento target viene identificato utilizzando visionText. Se è 0, l'azione dello script Robo sceglie il primo elemento corrispondente, se è 1, l'azione dello script Robo sceglie il secondo elemento corrispondente e così via. L'ordine è determinato da sinistra a destra, dall'alto verso il basso. Il valore predefinito è 0 (viene scelta la prima corrispondenza).

Il seguente attributo è facoltativo:

  • delayTime: specifica la durata della pressione di un clic lungo, in millisecondi.

Di seguito è riportato un esempio di azione di uno script Robo che esegue un clic di cinque secondi su un widget dell'interfaccia utente con la descrizione dei contenuti "Avatar 8":

{
  "eventType": "VIEW_LONG_CLICKED",
  "elementDescriptors": [
    {
      "contentDescription": "Avatar 8"
    }
  ],
  "delayTime": 5000
}

Esegui un gesto con un punto di contatto

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "ONE_POINT_GESTURE" --
coordinates Due coordinate per un gesto con un punto, formattate come "(x1,y1)->(x2,y2)" come percentuali o pixel.

Il seguente attributo è facoltativo:

  • dragAndDrop: se impostato su true, il gesto con un punto esegue un'azione di trascinamento. Il valore predefinito è false.

Di seguito è riportato un esempio di azione di un gesto a un punto di uno script Robo che esegue uno scorrimento verso il basso:

{
  "eventType": "ONE_POINT_GESTURE",
  "coordinates": "(50%,25%)->(50%,75%)"
}

Esegui un gesto con due punti di contatto

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "TWO_POINT_GESTURE" --
coordinates Quattro coordinate per un gesto a due punti, formattate come "(x1,y1)->(x2,y2),(x3,y3)->(x4,y4)" come percentuali o pixel.

Di seguito è riportato un esempio di azione di uno script Robo che esegue un gesto di allontanamento delle dita:

{
  "eventType": "TWO_POINT_GESTURE",
  "coordinates": "(50%,50%)->(25%,50%),(50%,50%)->(75%,50%)"
}

Esegui un'azione IME

Questa azione preme il pulsante di azione corrente, ad esempio Avanti, Fine e Cerca, nell'Input Method Editor (IME) per il widget UI di destinazione specificato.

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "PRESSED_EDITOR_ACTION" --
elementDescriptors Identifica il widget UI di destinazione utilizzando la gerarchia della UI di Android.

Di seguito è riportato un esempio di azione di uno script Robo che esegue un'azione IME su un widget UI con l'ID risorsa "com.google.samples.apps.topeka:id/first_name":

{
  "eventType": "PRESSED_EDITOR_ACTION",
  "elementDescriptors": [
    {
      "resourceId": "com.google.samples.apps.topeka:id/first_name"
    }
  ]
}

Premi Indietro

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
eventType Specifica il tipo di azione dello script Robo.
"eventType": "PRESSED_BACK" Invia un evento KEYCODE_BACK al dispositivo.
"eventType": "PRESSED_BACK_EMULATOR_28" Utilizzato dal registratore di script Robo in Android Studio per premere Indietro sugli emulatori API 28.

Di seguito è riportato un esempio di azione di uno script Robo che preme il pulsante Indietro:

{
  "eventType": "PRESSED_BACK"
}

Premi Home

Questa azione invia un evento KEYCODE_HOME al dispositivo.

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "GO_HOME" --

Di seguito è riportato un esempio di azione di uno script Robo che preme il tasto Home:

{
  "eventType": "GO_HOME"
}

Scorri finché l'elemento diventa visibile

Questa azione fa scorrere in avanti il widget della UI corrispondente al elementDescriptors specificato finché il widget della UI corrispondente al childElementDescriptors specificato non è presente sullo schermo, finché non è più possibile scorrere il widget o finché non viene raggiunto il numero massimo di 50 scorrimenti.

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "ELEMENT_SCROLL_INTO_VIEW" --
elementDescriptors Identifica il widget della UI che è stato fatto scorrere utilizzando la gerarchia della UI di Android.
childElementDescriptors Identifica il widget della UI verso cui scorrere utilizzando la gerarchia della UI di Android.

Di seguito è riportato un esempio di un'azione di script Robo che scorre il widget UI con l'ID risorsa "my.app.package:id/scrollable_card_container" finché il widget UI con il testo "Orange" non è presente sullo schermo (o non è più possibile eseguire scorrimenti o viene raggiunto il numero massimo di 50 scorrimenti):

{
  "eventType": "ELEMENT_SCROLL_INTO_VIEW",
  "elementDescriptors": [
    {
      "resourceId": "my.app.package:id/scrollable_card_container"
    }
  ],
  "childElementDescriptors": [
    {
      "text": "Orange"
    }
  ]
}

Scorri

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "VIEW_SWIPED" --
swipeDirection Specifica la direzione dello scorrimento:
  • Left
  • Right
  • Up
  • Down
  • Forward: Down o Right a seconda della possibilità di scorrimento verticale o orizzontale del widget UI di destinazione.
  • Backward: Up o Left a seconda della scorrevolezza verticale o orizzontale del widget UI di destinazione.
elementDescriptors Identifica il widget UI di destinazione utilizzando la gerarchia della UI di Android.

Di seguito è riportato un esempio di azione di uno script Robo che scorre verso l'alto un widget UI con l'ID risorsa "my.app.package:id/custom_content":

{
  "eventType": "VIEW_SWIPED",
  "swipeDirection": "Up",
  "elementDescriptors": [
    {
      "resourceId": "my.app.package:id/custom_content"
    }
  ]
}

Acquisisci screenshot

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "TAKE_SCREENSHOT" --
screenshotName Specifica il nome del file dello screenshot.

Di seguito è riportato un esempio di azione di uno script Robo che acquisisce uno screenshot:

{
  "eventType": "TAKE_SCREENSHOT",
  "screenshotName": "my_screenshot"
}

Tocca un punto sullo schermo

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "POINT_TAP" --
pointTapXCoordinate La coordinata X del pixel del punto toccato. Si esclude a vicenda con pointTapXPercent e pointTapYPercent.
pointTapYCoordinate La coordinata Y in pixel del punto toccato. Si esclude a vicenda con pointTapXPercent e pointTapYPercent.
pointTapXPercent La coordinata X percentuale del punto toccato. Si esclude a vicenda con pointTapXCoordinate e pointTapYCoordinate.
pointTapYPercent La coordinata Y percentuale del punto toccato. Si esclude a vicenda con pointTapXCoordinate e pointTapYCoordinate.

Di seguito è riportato un esempio di azione di uno script Robo che tocca il centro di una schermata:

{
  "eventType": "POINT_TAP",
  "pointTapXPercent": 50,
  "pointTapYPercent": 50
}

Tocca un punto all'interno di un elemento

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "POINT_TAP_ELEMENT" --
pointTapXPercent La coordinata X percentuale all'interno dell'elemento target.
pointTapYPercent La coordinata Y percentuale all'interno dell'elemento target.
elementDescriptors Identifica il widget UI di destinazione utilizzando la gerarchia della UI di Android.

Di seguito è riportato un esempio di azione di uno script Robo che sposta il cursore di una barra di ricerca verso destra:

{
  "eventType": "POINT_TAP_ELEMENT",
  "pointTapXPercent": 80,
  "pointTapYPercent": 50,
  "elementDescriptors": [
    {
      "resourceId": "my.app.package:id/my_seekbar"
    }
  ]
}

Termina scansione

Questa azione interrompe il test Robo.

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "TERMINATE_CRAWL" --

Di seguito è riportato un esempio di azione di uno script Robo che interrompe un test Robo:

{
  "eventType": "TERMINATE_CRAWL"
}

Attendi

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "WAIT" (or "DELAYED_MESSAGE_POSTED") --
delayTime Specifica il tempo di attesa in millisecondi.

Di seguito è riportato un esempio di azione di uno script Robo che attende tre secondi:

{
  "eventType": "WAIT",
  "delayTime": 3000
}

Attendi un elemento

Questa azione fa sì che il test Robo attenda che un elemento venga visualizzato sullo schermo fino al timeout specificato.

La tabella seguente elenca gli attributi obbligatori:

Attributo Descrizione
"eventType": "WAIT_FOR_ELEMENT" --
delayTime Specifica il timeout di attesa in millisecondi.
elementDescriptors Identifica il widget della UI in attesa utilizzando la gerarchia della UI di Android.

Di seguito è riportato un esempio di azione di uno script Robo che attende fino a 30 secondi che un widget UI con l'ID risorsa "my.app.package:id/confirmation_button" venga visualizzato sullo schermo:

{
  "eventType": "WAIT_FOR_ELEMENT",
  "delayTime": 30000,
  "elementDescriptors": [
    {
      "resourceId": "my.app.package:id/confirmation_button"
    }
  ]
}

Passaggi successivi