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 controllo qualità per le app mobile e consentono strategie di integrazione continua e test pre-lancio. Uno script Robo è un file JSON che descrive una sequenza di azioni dell'interfaccia utente (UI) e di altro tipo.
Puoi creare uno script Robo nei seguenti modi:
Utilizza la funzionalità di registrazione degli script Robo. (Solo Android)
Crea manualmente lo script Robo. (Android e iOS+)
Registra lo script Robo e poi modificalo manualmente. (Solo Android)
Per scoprire di più sull'utilizzo degli script Robo, consulta Eseguire uno script Robo.
Introduzione
Lo script Robo viene fornito al test Robo insieme ad altri input, come il pacchetto Android (APK) dell'app in fase di test.
Di seguito è riportato un esempio di script Robo che consente a un utente di accedere a un'app, che viene 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 e ha la condizione di attivazione
app_under_test_shown
predefinita, 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 Robo. La sintassi dello 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
I seguenti attributi identificativi nei descrittori degli elementi sono supportati in iOS+:
- Nome del corso
- Nome classe antenato
- Descrizione dei contenuti (ed espressione regolare)
- Testo (e regex)
Le seguenti condizioni di attivazione nei descrittori di contesto sono supportate in iOS+:
- App in fase di test mostrata
- Elemento presente
- Azione di script non Robo eseguita
Struttura
Uno script Robo ha diversi attributi che descrivono la modalità di esecuzione di Robo. 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 . Sebbene
lo stesso id in diversi script Robo non influenzi il loro
comportamento, distinguere le azioni da questi script Robo negli output di scansione
può essere difficile. Ti consigliamo di assegnare un id univoco di
1000 o superiore per gli 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à di 1 .
|
maxNumberOfRuns
|
Specifica il numero di volte in cui Robo può eseguire questo script Robo durante una scansione. Per impostazione predefinita, Robo può eseguire uno script Robo una sola 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, ovvero 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 un Robo script 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 che corrisponda a elementDescriptors o
al testo specificato da visionText .
|
"condition": "element_disabled"
|
Verifica che un widget UI corrispondente a elementDescriptors sia
presente sullo schermo e non possa essere utilizzato.
|
"condition": "element_checked"
|
Verifica che un widget 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 nessuna app è in esecuzione in primo piano. |
"condition": "non_roboscript_action_performed"
|
Verifica 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 ulteriori
informazioni, 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 dello script non Robo eseguite in precedenza. Viene
utilizzato in combinazione con la condizione non_roboscript_action_performed
per attivare uno script Robo dopo ogni
nonRoboscriptActionCount azioni 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 insieme 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 dell'interfaccia utente. Obbligatorio per tutte le azioni che hanno un widget UI di destinazione, ad esempio fare clic su un pulsante specifico. |
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 una schermata, senza che lo script Robo contenitore non riesca. 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 in pixel del punto toccato. Si escludono a vicenda
con pointTapXPercent e pointTapYPercent .
Obbligatorio per le azioni di tocco del 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 del 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 elemento identifica un widget UI utilizzando uno o più dei seguenti attributi di identificazione:
Attributo | Descrizione |
className
|
– |
ancestorClassName
|
Nome della classe dell'elemento padre della gerarchia dell'interfaccia utente. Un elemento principale è uno qualsiasi dei nodi padre 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 corrispondenze 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 alcuni valori degli attributi sono presenti,
potrebbero non essere univoci in una determinata schermata dell'app (incluso resourceId
).
Ad esempio, la distinzione tra gli elementi di un elenco è in genere possibile solo
utilizzando le diverse posizioni secondarie all'interno del widget principale. Ciò significa
che l'utilizzo di un solo descrittore di elemento per identificare un widget UI è in genere
insufficiente. 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
UI padre del widget di destinazione e così via. Il widget UI di destinazione di un'azione viene abbinato
quando tutti i relativi descrittori di elementi corrispondono alla gerarchia secondaria
del widget UI corrispondente.
Di seguito è riportato un esempio di script Robo con azioni di modifica del testo e clic, entrambe 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
Puoi aggiungere facoltativamente un prefisso all'elenco di azioni in uno script Robo con 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 sutrue
, lo script Robo non utilizza la corrispondenza parziale, il salto dell'azione corrente e la sospensione. ovvero lo script Robo viene eseguito come un normale test di strumentazione e non riesce non appena una delle sue azioni non può essere eseguita. Il valore predefinito èfalse
.dismiss_popups
- se impostato sutrue
, il test Robo chiude le finestre di dialogo impreviste durante l'esecuzione dello script Robo anche in modalitàstrict
. Questa opzione non ha effetto quando non è in modalitàstrict
. Il valore predefinito èfalse
.notify
: se impostato sufalse
, lo script Robo non mostra notifiche sullo schermo all'inizio e alla fine dell'esecuzione. Per impostazione predefinita, ètrue
.
postscript
- opzioni di esecuzione applicate al termine di uno script Robo:terminate
: se impostato sutrue
, 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 di 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 Robo supportano il seguente parametro del modello:
__%APP_PACKAGE_NAME%__
: il nome del pacchetto dell'app in fase di test.
Di seguito è riportato un esempio di script Robo che interrompe il processo dell'app in fase di 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é tutte le azioni non vengono completate (o almeno tentate). Il test Robo tenta continuamente 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 corrente dello script Robo non può essere abbinata completamente, i criteri di corrispondenza vengono rilassati e la corrispondenza viene riprovata. La corrispondenza parziale
non considera il descrittore dell'elemento più esterno durante la corrispondenza con il
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. |
Ignora l'azione corrente | Se l'azione corrente dello script Robo non può essere abbinata completamente o parzialmente,
Robo tenta di abbinare l'azione successiva dello script Robo. Se l'azione successiva
corrisponde completamente o parzialmente, il test Robo salta (e non torna mai)
all'azione corrente dello script Robo 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 e successive, lo script Robo viene sospeso temporaneamente 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é le azioni dello script Robo attuali o successive non possono essere abbinate, 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 gli scenari in cui il comportamento dell'app è instabile o quando le modifiche tra le versioni dell'app sono così grandi che Robo test deve "colmare le lacune" con le sue azioni standard. |
Priorità
Se uno script Robo raggiunge il maxNumberOfRuns
, non può più essere attivato
in una determinata scansione. Se più di uno script Robo può essere attivato dal contesto corrente, viene data la priorità scegliendo, nel seguente ordine, lo script Robo che:
- Ha un attributo
contextDescriptor
. - Ha il
priority
più alto (per impostazione predefinita, tutti gli script Robo hanno la stessa esecuzionepriority
di1
). - 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: 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 le seguenti azioni, in ordine:
"Robo script 2"
perché ha la priorità più alta."Robo script 1"
perché viene visualizzato prima tra i rimanenti script Robo applicabili con la stessa priorità."Robo script 3"
come ultimo script Robo applicabile.
Corse ripetute
Per impostazione predefinita, Robo attiva uno script Robo al massimo una volta durante una scansione. Può essere
regolato tramite l'attributo maxNumberOfRuns
.
Di seguito è riportato un esempio di script Robo che porta l'app in 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 a eseguire 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 principale di scansione, 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, quando vengono esplorate tutte le azioni possibili in questa schermata. Per impostazione predefinita, Robo preme Indietro, il che non è auspicabile in alcuni scenari. |
Se l'attributo crawlStage
di uno script Robo non è specificato, si presume che sia crawl
.
Di seguito è riportato un esempio di script Robo che cancella i dati utente dell'app in test prima che Robo inizi a eseguirne 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 vengono eseguite da Robo:
Attributo | Descrizione |
priority
|
La priorità di questa azione condizionale rispetto ad altre
azioni condizionali all'interno dello script Robo contenitore. Per impostazione predefinita, tutte le azioni condizionali hanno una priorità di 1 .
|
maxNumberOfRuns
|
Numero di volte in cui questa azione condizionale può essere eseguita durante una 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 contenente. |
contextDescriptor
|
Il contesto/la condizione che attiva questa azione condizionale. Ha la stessa struttura e offre funzionalità simili a contextDescriptor dello script Robo. |
Quando viene attivato, uno script Robo esegue le azioni non condizionali una alla volta 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 viene attivata e selezionata un'azione condizionale in base alla sua priorità e al numero di esecuzioni rimanenti, 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 ignorare widget UI specifici o tutti i widget UI su una schermata particolare. Queste istruzioni sono
rappresentate come ignorando le "azioni" con eventType
ELEMENT_IGNORED
e
ALL_ELEMENTS_IGNORED
rispettivamente.
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 a cui sono destinate le azioni di ignoramento (a meno che un'altra azione dello script Robo non costringa Robo a eseguire un'azione su uno dei widget UI ignorati).
Uno script Robo può contenere un mix di azioni di ignoranza, condizionali e non condizionali. A differenza di altre azioni dello script Robo, le azioni di ignoranza vengono applicate finché
il contextDescriptor
dello script Robo contenitore 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 in modo 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 in modo che
Robo ignori i widget UI i cui ID risorsa corrispondono all'espressione regolare Java ".*:id/done"
in 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
I figli dei widget RecyclerView e AdapterView vengono caricati dinamicamente e potrebbero essere visualizzati a molti swipe di distanza dalla schermata attuale. Poiché le dimensioni di uno schermo e il numero di scorrimenti necessari per raggiungere questo bambino variano a seconda dei fattori di forma del dispositivo, è molto più affidabile fare affidamento sulla posizione dei dati del bambino, che è assoluta. È un approccio meno solido fare affidamento sul numero di scorrimenti necessari per portare questo bambino sullo schermo e poi utilizzare la sua posizione sullo schermo.
Pertanto, lo script Robo acquisisce le posizioni assolute dei dati dei figli di RecyclerView
che sono destinatari delle azioni dello script Robo come
recyclerViewChildPosition
. Lo script Robo acquisisce anche le posizioni
assolute dei dati degli elementi secondari di AdapterView che sono destinatari delle azioni dello script Robo come
adapterViewChildPosition
.
Le azioni sugli elementi secondari di RecyclerView e AdapterView vengono eseguite nei seguenti passaggi:
Il test Robo garantisce che il bambino corrispondente venga visualizzato sullo schermo tramite un'azione di posizionamento sul RecyclerView o sull'AdapterView contenitore.
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 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 salva lo script 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 nello script e poi esegue la scansione dell'app come al solito.
Per creare un file JSON di Robo script in Android Studio, segui i passaggi descritti in Registrare uno script Robo utilizzando Test Lab in Android Studio.
Azioni dello 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 asserita è 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 asserita. Ha la stessa struttura e offre funzionalità simili a contextDescriptor di Robo script. |
Di seguito è riportato un esempio di asserzione di 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 dello script Robo che verifica che un widget
UI con l'ID risorsa "com.google.samples.apps.topeka:id/done"
sia
presente su una schermata:
{
"eventType": "ASSERTION",
"contextDescriptor": {
"condition": "element_present",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/done"
}
]
}
}
Di seguito è riportato un esempio di asserzione di script Robo che verifica
che "Settings"
NON venga rilevato su una schermata 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"
|
Fai clic sull'elemento di destinazione dell'app in fase di test. |
"eventType": "SOFT_KEYBOARD_CLICK"
|
Fai clic sull'elemento di destinazione della tastiera virtuale. |
"eventType": "SOFT_KEYBOARD_RANDOM_CLICK"
|
Fa clic su elementi casuali della tastiera virtuale 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 UI su cui è stato fatto clic utilizzando la gerarchia UI di Android.
Si esclude a vicenda con visionText .
|
visionText
|
Identifica l'elemento su cui è stato fatto clic 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 e dall'alto verso il basso. Il valore
predefinito è 0 (viene selezionata la prima corrispondenza).
|
maxNumberOfRuns
|
Specifica il numero di volte in cui fare clic su un elemento casuale della tastiera virtuale,
quando eventType è SOFT_KEYBOARD_RANDOM_CLICK .
Il valore predefinito è 1 .
|
Di seguito è riportato un esempio di azione dello 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 dello script Robo che fa clic sulla seconda
occorrenza della parola "Search"
rilevata su una schermata utilizzando l'OCR:
{
"eventType": "VIEW_CLICKED",
"visionText": "Search",
"matchIndex": 1
}
Di seguito è riportato un esempio di azione dello script Robo che fa clic su un elemento della tastiera
virtuale con una descrizione dei contenuti "Emoji button"
:
{
"eventType": "SOFT_KEYBOARD_CLICK",
"elementDescriptors": [
{
"contentDescription": "Emoji button"
}
]
}
Di seguito è riportato un esempio di azione dello script Robo che fa clic su elementi casuali della tastiera software fino a cinque volte:
{
"eventType": "SOFT_KEYBOARD_RANDOM_CLICK",
"maxNumberOfRuns": 5
}
Disattivare la tastiera virtuale
La tabella seguente elenca gli attributi obbligatori:
Attributo | Descrizione |
"eventType": "DISABLE_KEYBOARD"
|
-- |
Di seguito è riportato un esempio di azione di Robo script che disattiva la tastiera software:
{
"eventType": "DISABLE_KEYBOARD"
}
Esegui il comando adb shell
La tabella seguente elenca gli attributi obbligatori:
Attributo | Descrizione |
"eventType": "ADB_SHELL_COMMAND"
|
-- |
command
|
Il comando 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 dello script Robo che cancella i dati utente dell'app in 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 ha effetto. NON utilizzare questa azione negli script Robo.
La tabella seguente elenca gli attributi obbligatori:
Attributo | Descrizione |
"eventType": "PERMISSIONS_REQUEST"
|
-- |
Ignorare tutti gli elementi di una schermata
Questa azione fa in modo che Robo ignori tutti gli elementi di qualsiasi schermata che attiva lo script Robo contenitore.
La tabella seguente elenca gli attributi obbligatori:
Attributo | Descrizione |
"eventType": "ALL_ELEMENTS_IGNORED"
|
-- |
Di seguito è riportato un esempio di azione dello script Robo che fa in modo che Robo ignori tutti gli elementi di una schermata:
{
"eventType": "ALL_ELEMENTS_IGNORED"
}
Ignorare un elemento
Questa azione fa in modo che Robo ignori uno o più elementi che corrispondono al
elementDescriptors
specificato.
La tabella seguente elenca gli attributi obbligatori:
Attributo | Descrizione |
"eventType": "ELEMENT_IGNORED"
|
-- |
elementDescriptors
|
Identifica i widget UI ignorati utilizzando la gerarchia UI di Android. |
Il seguente attributo è facoltativo:
ignoreChildren
: se impostato sutrue
, Robo ignora anche tutti i discendenti dei widget UI ignorati. Il valore predefinito èfalse
.
Di seguito è riportato un esempio di azione dello script Robo che fa in modo 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 dell'interfaccia utente 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 dell'interfaccia utente di destinazione utilizzando la gerarchia dell'interfaccia utente di Android. |
replacementText
|
Il testo da inserire nel widget dell'interfaccia utente di destinazione. |
Di seguito è riportato un esempio di azione dello script Robo che inserisce "John"
in
un widget 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 dell'interfaccia utente di destinazione utilizzando la gerarchia dell'interfaccia utente di Android. Esclusivo
con visionText .
|
visionText
|
Identifica l'elemento su cui è stato eseguito un clic 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 e dall'alto verso il basso. Il valore
predefinito è 0 (viene selezionata 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 dello script Robo che esegue un clic di cinque
secondi su un widget UI con la descrizione dei contenuti "Avatar 8"
:
{
"eventType": "VIEW_LONG_CLICKED",
"elementDescriptors": [
{
"contentDescription": "Avatar 8"
}
],
"delayTime": 5000
}
Eseguire un gesto con un solo punto
La tabella seguente elenca gli attributi obbligatori:
Attributo | Descrizione |
---|---|
"eventType": "ONE_POINT_GESTURE"
|
-- |
coordinates
|
Due coordinate per un gesto a un punto, formattate come "(x1,y1)->(x2,y2)" come percentuali o pixel. |
Il seguente attributo è facoltativo:
dragAndDrop
: se impostato sutrue
, il gesto con un solo dito esegue un'azione di trascinamento. Il valore predefinito èfalse
.
Di seguito è riportato un esempio di azione di scorrimento verso il basso con un solo dito di uno script Robo:
{
"eventType": "ONE_POINT_GESTURE",
"coordinates": "(50%,25%)->(50%,75%)"
}
Eseguire un gesto a due punti
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 dello script Robo che esegue un gesto di pizzico in uscita:
{
"eventType": "TWO_POINT_GESTURE",
"coordinates": "(50%,50%)->(25%,50%),(50%,50%)->(75%,50%)"
}
Eseguire 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 dell'interfaccia utente di destinazione utilizzando la gerarchia dell'interfaccia utente di Android. |
Di seguito è riportato un esempio di azione dello 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 sull'API 28 degli emulatori. |
Di seguito è riportato un esempio di azione dello script Robo che preme 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 dello script Robo che preme il tasto Home:
{
"eventType": "GO_HOME"
}
Scorrere un elemento finché non diventa visibile
Questa azione fa scorrere in avanti il widget UI che corrisponde al
elementDescriptors
specificato finché il widget UI che corrisponde al
childElementDescriptors
specificato non è presente sullo schermo, oppure il widget scorre
non può più essere scorrevole o 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 UI scorrevole utilizzando la gerarchia dell'interfaccia utente di Android. |
childElementDescriptors
|
Identifica il widget UI a cui scorrere utilizzando la gerarchia UI di Android. |
Di seguito è riportato un esempio di azione dello 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 scorrere 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:
|
elementDescriptors
|
Identifica il widget dell'interfaccia utente di destinazione utilizzando la gerarchia dell'interfaccia utente di Android. |
Di seguito è riportato un esempio di azione dello 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 dello 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 in 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 dello 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 dell'interfaccia utente di destinazione utilizzando la gerarchia dell'interfaccia utente di Android. |
Di seguito è riportato un esempio di azione dello 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 dello 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 dello script Robo che attende tre secondi:
{
"eventType": "WAIT",
"delayTime": 3000
}
Attendi un elemento
Questa azione fa sì che il test Robo attenda la visualizzazione di un elemento 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 UI in attesa utilizzando la gerarchia dell'interfaccia utente di Android. |
Di seguito è riportato un esempio di azione dello script Robo che attende fino a 30
secondi che sullo schermo venga visualizzato un widget UI con l'ID risorsa
"my.app.package:id/confirmation_button"
:
{
"eventType": "WAIT_FOR_ELEMENT",
"delayTime": 30000,
"elementDescriptors": [
{
"resourceId": "my.app.package:id/confirmation_button"
}
]
}