В этом документе представлена справочная информация о скриптах Robo, включая структуру, возможности, использование, запись и действия. Скрипты Robo — это тесты, автоматизирующие ручные задачи контроля качества (QA) мобильных приложений и обеспечивающие стратегии непрерывной интеграции (CI) и предпускового тестирования. Скрипт Robo — это JSON-файл, описывающий последовательность действий пользовательского интерфейса (UI) и других действий.
Создать Robo-скрипт можно следующими способами:
Используйте функцию записи скриптов Robo. (Только для Android)
Создайте скрипт Robo вручную. (Android и iOS+)
Запишите скрипт Robo, а затем отредактируйте его вручную. (Только для Android)
Дополнительную информацию об использовании скриптов Robo см. в разделе Запуск скрипта Robo .
Введение
Скрипт Robo предоставляется для тестирования Robo вместе с другими входными данными, такими как пакет Android-приложения (APK) для тестируемого приложения.
Ниже приведен пример скрипта Robo, который регистрирует пользователя в приложении и срабатывает при запуске тестируемого приложения:
[
{
"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"
}
]
}
]
}
]
Если в файле есть один скрипт Robo и у него есть условие срабатывания по умолчанию app_under_test_shown
, как в примере выше, то вы можете указать скрипт Robo в файле, используя более простой формат — просто как последовательность его действий:
[
{
"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"
}
]
}
]
Поддержка iOS+ для скриптов Robo
Robo для iOS+ (бета-версия) имеет ограниченную поддержку скриптов Robo. Синтаксис скрипта Robo для iOS+ идентичен синтаксису Android, а поддерживаемые функции iOS+ работают аналогично своим аналогам в Android.
В iOS+ поддерживаются следующие действия:
- Утверждение
- Щелкните
- Длительный щелчок
- Проведите пальцем
- Игнорировать все элементы
- Ждать
- Сделать снимок экрана
- Прекратить сканирование
В iOS+ поддерживаются следующие идентифицирующие атрибуты в дескрипторах элементов:
- Имя класса
- Имя класса-предка
- Описание содержимого (и регулярное выражение)
- Текст (и регулярное выражение)
В iOS+ поддерживаются следующие условия срабатывания в контекстных дескрипторах :
- Показано тестируемое приложение
- Элемент присутствует
- Выполнено действие не-роботизированного скрипта
Структура
У скрипта Robo есть несколько атрибутов, описывающих, как он выполняется. Большинство этих атрибутов необязательны и имеют предопределённые значения по умолчанию:
Атрибут | Описание |
id | Целое число, которое помогает отслеживать этот скрипт Robo в результатах сканирования. В Robo есть встроенные скрипты Robo с собственными id . Хотя одинаковый id в разных скриптах Robo не влияет на их поведение, различение действий, выполняемых этими скриптами Robo в результатах сканирования, может быть сложной задачей. Мы рекомендуем назначать вашим скриптам Robo уникальный id 1000 или выше, чтобы избежать конфликтов. |
description | Похож на id , но более описательный. |
crawlStage | Этап сканирования, на котором Robo применяет этот скрипт. По умолчанию это основной этап сканирования. |
priority | Приоритет этого скрипта Robo по сравнению с другими скриптами Robo. По умолчанию все скрипты Robo имеют приоритет 1 . |
maxNumberOfRuns | Указывает, сколько раз за сканирование Robo может выполнить данный скрипт Robo. По умолчанию Robo может выполнить скрипт Robo один раз. |
contextDescriptor | Описывает контекст или условие, запускающее данный скрипт Robo. Если этот аргумент опущен, условие запуска данного скрипта Robo считается выполненным всегда; другими словами, скрипт Robo является безусловным. |
actions | Все действия этого скрипта Robo. |
Один файл содержит набор из одного или нескольких скриптов Robo.
Ниже приведен пример файла с двумя безусловными скриптами Robo, каждый из которых содержит одно действие, выполняемое один раз в начале сканирования:
[
{
"id": 1000,
"description": "My first Robo script",
"actions": [
{
"eventType": "DISABLE_KEYBOARD"
}
]
},
{
"id": 1001,
"description": "My second Robo script",
"actions": [
{
"eventType": "PRESSED_BACK"
}
]
}
]
Контекстный дескриптор
Дескриптор контекста определяет контекст или условие, которое запускает скрипт Robo, используя один или комбинацию нескольких атрибутов:
Атрибут | Описание |
---|---|
"condition": "always" | Всегда запускает скрипт Robo. |
"condition": "element_present" | Проверяет наличие на экране виджета пользовательского интерфейса, соответствующего elementDescriptors или тексту, указанному visionText . |
"condition": "element_disabled" | Проверяет, присутствует ли на экране виджет пользовательского интерфейса, соответствующий elementDescriptors , и невозможно ли с ним взаимодействовать. |
"condition": "element_checked" | Проверяет, присутствует ли на экране виджет пользовательского интерфейса, соответствующий elementDescriptors , и отмечен ли он. |
"condition": "app_under_test_shown" | Проверяет, запущено ли тестируемое приложение на переднем плане. |
"condition": "default_launcher_shown" | Проверяет, отображается ли домашний экран устройства, что означает, что на переднем плане не запущено ни одного приложения. |
"condition": "non_roboscript_action_performed" | Проверяет, что последние nonRoboscriptActionCount последовательные действия, выполненные тестом Robo, не являются действиями скрипта Robo. |
negateCondition | Если установлено значение true , condition отменяется. Например, этот атрибут можно использовать для проверки того, отсутствует ли на экране виджет пользовательского интерфейса или не запущено ли тестируемое приложение на переднем плане. |
elementDescriptors | Один или несколько дескрипторов элементов, идентифицирующих виджет пользовательского интерфейса на экране. Используется в сочетании с условиями element_present , element_disabled и element_checked . Взаимоисключающее с visionText . Подробнее см. в разделе Дескрипторы элементов . |
visionText | Текст на экране распознаётся с помощью API оптического распознавания символов (OCR). visionText используется в сочетании с условием element_present . Взаимоисключающее с elementDescriptors . |
nonRoboscriptActionCount | Количество последовательных действий, выполненных ранее (не Robo-скрипт). Используется в сочетании с условием non_roboscript_action_performed для запуска Robo-скрипта после каждых nonRoboscriptActionCount действий Robo. По умолчанию равно 1 . |
Ниже приведен пример скрипта Robo, который запускается виджетом пользовательского интерфейса с идентификатором ресурса "my.app.package:id/page_header"
присутствующим на экране:
{
"id": 1000,
"contextDescriptor": {
"condition": "element_present",
"elementDescriptors": [
{
"resourceId": "my.app.package:id/page_header"
}
]
},
"actions": [
{
"eventType": "VIEW_CLICKED",
"elementDescriptors": [
{
"text": "Settings"
}
]
}
]
}
Ниже приведен пример скрипта Robo, который запускается при обнаружении "Privacy Policy"
с помощью оптического распознавания символов (OCR):
{
"id": 1000,
"description": "Vision text Robo script",
"contextDescriptor": {
"condition": "element_present",
"visionText": "Privacy Policy"
},
"actions": [
{
"eventType": "VIEW_CLICKED",
"visionText": "Privacy Policy"
}
]
}
Ниже приведен пример скрипта Robo, который ждет 5 секунд после каждого действия Robo, не являющегося скриптом:
{
"contextDescriptor": {
"condition": "non_roboscript_action_performed"
},
"maxNumberOfRuns" : 1000,
"actions" : [
{
"eventType" : "WAIT",
"delayTime" : 5000
}]
}
Действия
Каждое действие в скрипте Robo представлено в виде набора из одной или нескольких пар «атрибут-значение», которые описаны в следующей таблице:
Атрибут | Описание |
eventType | Указывает тип действия, например, щелчок, редактирование текста и т. д. Обязательно для каждого действия. |
elementDescriptors | Дескрипторы, идентифицирующие виджет пользовательского интерфейса. Обязательны для всех действий, имеющих целевой виджет пользовательского интерфейса, например, нажатие определенной кнопки. |
optional | Если задано значение true , это действие пропускается, если его невозможно выполнить. Например, это действие пропускается, если не удаётся найти целевой виджет пользовательского интерфейса на экране, не нарушая при этом выполнение содержащего его скрипта Robo. По умолчанию значение равно false . |
replacementText | Текст для ввода в целевой виджет пользовательского интерфейса. Требуется для редактирования текста. |
swipeDirection | Задаёт направление свайпа. Требуется для действий свайпа. |
delayTime | Указывает время ожидания в миллисекундах. Требуется для действий ожидания. |
pointTapXCoordinate и pointTapYCoordinate | Координаты X и Y точки касания в пикселях. Взаимоисключающие с pointTapXPercent и pointTapYPercent . Требуется для действий касания точки. |
pointTapXPercent и pointTapYPercent | Процентные координаты X и Y точки касания. Взаимоисключающее с pointTapXCoordinate и pointTapYCoordinate . Требуется для действий касания точки. |
Ниже приведен пример скрипта Robo с двумя действиями без целевых виджетов пользовательского интерфейса. Это означает, что эти действия не работают с конкретным виджетом пользовательского интерфейса:
[
{
"eventType": "WAIT",
"delayTime": 3000
},
{
"eventType": "PRESSED_BACK"
}
]
Дескрипторы элементов
Дескриптор элемента идентифицирует виджет пользовательского интерфейса, используя один или несколько из следующих идентифицирующих атрибутов:
Атрибут | Описание |
className | – |
ancestorClassName | Имя класса предка иерархии пользовательского интерфейса элемента. Предком является любой родительский узел в иерархии пользовательского интерфейса элемента, включая сам элемент. |
resourceId | – |
resourceIdRegex | Регулярное выражение Java для сопоставления resourceId . |
contentDescription | – |
contentDescriptionRegex | Регулярное выражение Java для сопоставления contentDescription . |
text (который появляется на экране) | – |
textRegex | Регулярное выражение Java для сопоставления text . |
groupViewChildPosition , recyclerViewChildPosition или adapterViewChildPosition | Представляет дочернюю позицию виджета пользовательского интерфейса в зависимости от типа его родительского виджета. |
Часто эти атрибуты не определены, например, кнопка может не иметь текста и описания содержимого. Даже если некоторые значения атрибутов присутствуют, они могут быть неуникальными на данном экране приложения (включая resourceId
).
Например, различить элементы списка обычно можно только по разным позициям их дочерних элементов в родительском виджете. Это означает, что использования одного дескриптора элемента для идентификации виджета пользовательского интерфейса обычно недостаточно. Поэтому атрибут elementDescriptors
действия содержит последовательность дескрипторов элементов, упорядоченных таким образом, что первый соответствует целевому виджету пользовательского интерфейса, второй — родительскому виджету целевого виджета пользовательского интерфейса и так далее. Целевой виджет пользовательского интерфейса действия считается соответствующим, когда все его дескрипторы элементов соответствуют соответствующей подиерархии виджетов пользовательского интерфейса.
Ниже приведен пример скрипта Robo с действиями по изменению текста и щелчку, оба из которых требуют от вас определения целевого виджета пользовательского интерфейса с помощью предоставленных дескрипторов элементов:
[
{
"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"
}
]
}
]
Варианты исполнения
При желании вы можете добавить к списку действий в скрипте Robo префикс JSON-объект, определяющий параметры выполнения этого скрипта. Этот заголовок конфигурации начинается с ключевого слова roboscript
, за которым следует JSON-представление требуемых параметров выполнения.
Скрипты Robo поддерживают следующие варианты выполнения:
-
executionMode
— параметры выполнения, применяемые при запуске скрипта Robo:-
strict
— если установлено значениеtrue
, скрипт Robo не использует частичное сопоставление, пропуск текущего действия и приостановку . То есть скрипт Robo выполняется как обычный инструментальный тест и завершается неудачей, как только любое из его действий становится невозможным. По умолчанию установлено значениеfalse
. -
dismiss_popups
— если установлено значениеtrue
, Robo-тест закрывает любые непредвиденные диалоговые окна при выполнении скрипта Robo даже вstrict
режиме. Этот параметр не действует внеstrict
режима. По умолчанию он равенfalse
. -
notify
— если установлено значениеfalse
, скрипт Robo не будет выводить на экран уведомления в начале и конце своего выполнения. По умолчанию установленоtrue
.
-
-
postscript
- параметры выполнения, применяемые после завершения скрипта Robo:-
terminate
— если установлено значениеtrue
, Robo-тест останавливает сканирование после завершения скрипта Robo. По умолчанию установлено значениеfalse
.
-
Ниже приведен пример скрипта Robo, выполняемого в strict
режиме без экранных уведомлений, который ждет три секунды, после чего сканирование останавливается:
"roboscript": {
"executionMode": {
"strict": true,
"notify": false
},
"postscript": {
"terminate": true
}
}
[
{
"eventType": "WAIT",
"delayTime": 3000
}
]
Параметры шаблона
Параметр шаблона — это заглушка в скрипте Robo, которая заменяется фактическим значением при загрузке скрипта Robo тестом Robo для выполнения. Параметры шаблона имеют префикс в виде двойного подчёркивания, за которым следует знак процента, и постфикс в виде двойного подчёркивания, за которым следует знак процента.
Скрипты Robo поддерживают следующий параметр шаблона:
-
__%APP_PACKAGE_NAME%__
- имя пакета тестируемого приложения.
Ниже приведен пример скрипта Robo, который останавливает процесс тестирования приложения:
[
{
"eventType": "ADB_SHELL_COMMAND",
"command": "am force-stop __%APP_PACKAGE_NAME%__"
}
]
Комментарии
Скрипт Robo может содержать строки комментариев, которые начинаются с #
или //
.
Ниже приведен пример скрипта Robo с несколькими комментариями:
# Confirm a user account.
[
{
// Click the DONE button.
"eventType": "VIEW_CLICKED",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/done"
}
]
}
]
Возможности
По умолчанию, пока все действия скрипта Robo не будут выполнены (или хотя бы попытаются их выполнить), скрипт Robo остаётся активным. Тест Robo постоянно пытается выполнить действие скрипта Robo при каждом выборе действия для выполнения. Скрипт Robo использует следующие методы для повышения надёжности:
Техника | Описание |
Частичное совпадение | Если текущее действие скрипта Robo не может быть полностью сопоставлено, критерии сопоставления ослабляются, и попытка сопоставления повторяется. При частичном сопоставлении дескриптор самого внешнего элемента не учитывается при сопоставлении целевого виджета пользовательского интерфейса действия скрипта Robo. Если частичное совпадение успешно, соответствующее действие скрипта Robo выполняется в обычном режиме. Этот метод поддерживает сценарии, в которых структура приложения изменяется, например, при смене версии приложения, когда элементы экрана перестраиваются. |
Пропустить текущее действие | Если текущее действие скрипта Robo не может быть полностью или частично совпало, Robo пытается совпасть со следующим действием скрипта Robo. Если последующее действие полностью или частично совпадает, тест Robo пропускает (и никогда не возвращается к) текущее действие скрипта Robo и выполняет следующее. Эта технология поддерживает сценарии, когда поведение приложения меняется между версиями или нестабильно, например, когда прерывистый диалог может появляться на разных экранах во время записи или воспроизведения скрипта Robo. |
Приостановить | Если ни текущее, ни последующие действия Robo-скрипта не могут быть полностью или частично сопоставлены, Robo-скрипт временно приостанавливается, и Robo-тест выбирает действие для выполнения, используя другие стратегии. После завершения этого действия Robo-тест возобновляет выполнение Robo-скрипта. Пока текущие или последующие действия скрипта Robo не могут быть сопоставлены, скрипт Robo остаётся приостановленным для любого количества действий. Таким образом, скрипты Robo не обязательно должны быть прологом для теста Robo, и вы можете чередовать действия скрипта Robo со стандартными действиями теста Robo. Этот метод подходит для ситуаций, когда поведение приложения нестабильно или когда изменения между версиями приложения настолько велики, что тесту Robo приходится «заполнять пробелы» своими стандартными действиями. |
Приоритеты
Если скрипт Robo достигает своего maxNumberOfRuns
, он больше не может быть запущен в данном цикле сканирования. Если текущий контекст может запустить более одного скрипта Robo, приоритет отдаётся выбору скрипта Robo в следующем порядке:
- Имеет атрибут
contextDescriptor
. - Имеет наивысший
priority
(по умолчанию все скрипты Robo имеют одинаковыйpriority
выполнения1
). - Появляется первым в списке скриптов Robo, если приоритеты скриптов Robo одинаковы.
Ниже приведен пример файла с тремя скриптами Robo, которые выполняют одно и то же действие и запускаются при одном и том же условии — тестируемое приложение находится на переднем плане:
[
{
"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
}
]
}
]
Когда тестируемое приложение находится на переднем плане, Robo запускает следующие процессы в следующем порядке:
-
"Robo script 2"
, поскольку он имеет наивысший приоритет. -
"Robo script 1"
поскольку он появляется раньше среди оставшихся применимых Robo-скриптов с тем же приоритетом. -
"Robo script 3"
— последний применимый Robo-скрипт.
Повторные прогоны
По умолчанию Robo запускает скрипт Robo не чаще одного раза за сканирование. Это можно изменить с помощью атрибута maxNumberOfRuns
.
Ниже приведен пример скрипта Robo, который переводит тестируемое приложение в фоновый режим до 10 раз:
{
"id": 1000,
"maxNumberOfRuns": 10,
"contextDescriptor": {
"condition": "app_under_test_shown"
},
"actions": [
{
"eventType": "GO_HOME"
}
]
}
Стадия ползания
Скрипты Robo применимы на разных этапах конкретного роботизированного сканирования:
Стадия ползания | Описание |
pre_crawl | До того, как Robo запустится и начнет сканировать тестируемое приложение. |
post_crawl | После того, как Robo завершит сканирование тестируемого приложения. Длительность скрипта post_crawl Robo не должна превышать 15 секунд, иначе сканирование может быть прервано по тайм-ауту. |
crawl | Основной этап сканирования, когда Robo сканирует тестируемое приложение. |
close_screen | Когда Робот пытается вернуться назад (бэктрек) с заданного экрана, после того как все возможные действия на этом экране уже исчерпаны. По умолчанию Робот нажимает кнопку «Назад», что в некоторых сценариях нежелательно. |
Если атрибут crawlStage
скрипта Robo не указан, подразумевается, что это crawl
.
Ниже приведен пример скрипта Robo, который очищает данные пользователя тестируемого приложения перед тем, как Robo начнет его сканирование:
{
"id": 1000,
"crawlStage": "pre_crawl",
"actions": [
{
"eventType": "ADB_SHELL_COMMAND",
"command": "pm clear __%APP_PACKAGE_NAME%__"
}
]
}
Ниже приведен пример скрипта Robo, который дает команду Robo нажимать кнопку "Cancel"
каждый раз, когда он пытается вернуться назад (вернуться) из диалогового окна подтверждения:
{
"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"
}
]
}
]
}
Условные действия
Скрипт Robo может содержать условные действия. Условные действия имеют три дополнительных атрибута, описывающих, как Robo их выполняет:
Атрибут | Описание |
priority | Приоритет данного условного действия по сравнению с другими условными действиями в содержащем его скрипте Robo. По умолчанию все условные действия имеют приоритет 1 . |
maxNumberOfRuns | Сколько раз это условное действие может быть выполнено за одно выполнение содержащего его скрипта Robo? По умолчанию все условные действия могут быть выполнены не более одного раза за одно выполнение содержащего их скрипта Robo. |
contextDescriptor | Контекст/условие, запускающее это условное действие. Он имеет ту же структуру и предлагает те же возможности, что и contextDescriptor скрипта Robo. |
При запуске скрипт Robo выполняет безусловные действия одно за другим в порядке их появления. Если скрипт Robo содержит условные действия, они учитываются каждый раз перед выбором безусловного действия. Если какое-либо условное действие срабатывает и выбирается на основе его приоритета и оставшегося количества запусков, скрипт Robo выполняет это условное действие. В противном случае скрипт Robo выполняет следующее безусловное действие. Чтобы быть корректным, скрипт Robo должен содержать хотя бы одно безусловное действие.
Ниже приведен пример безусловного скрипта Robo с условным действием, которое закрывает всплывающие диалоговые окна, если они появляются в любой момент выполнения скрипта 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
}
}
Игнорирование действий
Скрипт Robo может содержать инструкции, позволяющие Robo игнорировать определённые виджеты пользовательского интерфейса или все виджеты на определённом экране. Эти инструкции представлены как игнорирование «действий» с eventType
ELEMENT_IGNORED
и ALL_ELEMENTS_IGNORED
соответственно.
Всякий раз, когда атрибут contextDescriptor
скрипта Robo, содержащего игнорируемые действия, соответствует заданному экрану, Robo не взаимодействует ни с какими виджетами пользовательского интерфейса, на которые нацелены его игнорируемые действия (если только какое-либо другое действие скрипта Robo не заставляет Robo выполнить действие над одним из игнорируемых виджетов пользовательского интерфейса).
Скрипт Robo может содержать сочетание игнорирующих, условных и безусловных действий. В отличие от других действий скрипта Robo, игнорирующие действия применяются до тех пор, пока contextDescriptor
содержащего их скрипта Robo совпадает с экраном во время сканирования, независимо от значений атрибутов priority
и maxNumberOfRuns
.
Ниже приведён пример файла с двумя скриптами Robo. Первый скрипт Robo заставляет Robo игнорировать все виджеты пользовательского интерфейса на экране, содержащем виджет с идентификатором ресурса "my.app.package:id/ignored_screen"
. Второй скрипт Robo заставляет Robo игнорировать виджеты пользовательского интерфейса, идентификаторы ресурсов которых соответствуют регулярному выражению Java ".*:id/done"
на экране, содержащем виджет с идентификатором ресурса "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"
}
]
}
]
}
]
Поддержка RecyclerView и AdapterView
Дочерние элементы виджетов RecyclerView и AdapterView загружаются динамически и могут отображаться на расстоянии многих свайпов от текущего экрана. Поскольку размер экрана и количество свайпов, необходимых для перехода к дочернему элементу, различаются для разных форм-факторов устройств, гораздо надёжнее полагаться на абсолютное положение данных дочернего элемента. Менее надёжным подходом является использование количества свайпов, необходимых для перехода к дочернему элементу на экран, и последующего использования его положения на экране.
Таким образом, скрипт Robo фиксирует абсолютные позиции данных дочерних элементов RecyclerView, являющихся целями действий скрипта Robo, как recyclerViewChildPosition
. Скрипт Robo также фиксирует абсолютные позиции данных дочерних элементов AdapterView, являющихся целями действий скрипта Robo, как adapterViewChildPosition
.
Действия над дочерними элементами RecyclerView и AdapterView выполняются следующим образом:
Robo-тест обеспечивает отображение соответствующего дочернего элемента на экране посредством действия позиционирования на содержащем его RecyclerView или AdapterView.
Robo-тест выполняет записанное действие непосредственно над дочерним элементом, поскольку он уже отображается на экране.
Ниже приведен пример действия щелчка по дочернему элементу 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
}
]
}
Ниже приведен пример действия щелчка по дочернему элементу 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
}
]
}
Запишите скрипт Robo в Android Studio и запустите его в Test Lab
Вы можете создать скрипт Robo в Android Studio, который сохранит его в виде JSON-файла. Затем вы можете загрузить JSON-файл в Firebase Test Lab вместе с приложением и запустить тест.
При запуске Robo-теста с прикрепленным сценарием Robo-тест сначала выполняет заранее заданные действия, а затем исследует приложение как обычно.
Чтобы создать JSON-файл скрипта Robo в Android Studio, следуйте инструкциям в разделе Запись скрипта Robo с помощью Test Lab в Android Studio .
Действия скрипта Robo
Следующий общий необязательный атрибут применяется ко всем действиям:
-
description
- помогает отслеживать выполнение этого действия скрипта Robo в выходных данных теста Robo.
Утверждение
Если условие выполнено, скрипт Robo переходит к следующему действию, которое может быть другим утверждением. В противном случае выполнение скрипта Robo останавливается из-за невыполненного утверждения.
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "ASSERTION" | -- |
contextDescriptor | Описывает заданный контекст или условие. Имеет ту же структуру и предлагает аналогичные возможности, что и contextDescriptor скрипта Robo . |
Ниже приведен пример утверждения скрипта Robo, который проверяет, находится ли тестируемое приложение на переднем плане:
{
"eventType": "ASSERTION",
"contextDescriptor": {
"condition": "app_under_test_shown"
}
}
Ниже приведен пример утверждения скрипта Robo, который проверяет наличие на экране виджета пользовательского интерфейса с идентификатором ресурса "com.google.samples.apps.topeka:id/done"
:
{
"eventType": "ASSERTION",
"contextDescriptor": {
"condition": "element_present",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/done"
}
]
}
}
Ниже приведен пример утверждения скрипта Robo, который проверяет, что "Settings"
НЕ обнаружены на экране с помощью OCR:
{
"eventType": "ASSERTION",
"contextDescriptor": {
"condition": "element_present",
"negateCondition": true,
"visionText": "Settings"
}
}
Щелкните
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
---|---|
eventType | Указывает тип действия скрипта Robo. |
"eventType": "VIEW_CLICKED" | Кликает по целевому элементу тестируемого приложения. |
"eventType": "SOFT_KEYBOARD_CLICK" | Кликает по целевому элементу экранной клавиатуры. |
"eventType": "SOFT_KEYBOARD_RANDOM_CLICK" | Нажимает на случайные элементы экранной клавиатуры до maxNumberOfRuns раз. |
"eventType": "LIST_ITEM_CLICKED" | Используется средством записи скриптов Robo в Android Studio для нажатия на элементы списка. |
elementDescriptors | Идентифицирует выбранный виджет пользовательского интерфейса, используя иерархию пользовательского интерфейса Android. Взаимоисключающее с visionText . |
visionText | Идентифицирует выбранный элемент с помощью OCR. Взаимоисключающее с elementDescriptors . |
matchIndex | Задаёт индекс вхождения совпавшего целевого элемента, если целевой элемент идентифицирован с помощью visionText . Если он равен 0 , действие скрипта Robo выбирает первый совпавший элемент, если он равен 1 , действие скрипта Robo выбирает второй совпавший элемент и т. д. Порядок определяется слева направо, сверху вниз. Значение по умолчанию — 0 (выбирается первое совпадение). |
maxNumberOfRuns | Указывает, сколько раз следует нажать случайный элемент экранной клавиатуры, если eventType — SOFT_KEYBOARD_RANDOM_CLICK . Значение по умолчанию — 1 . |
Ниже приведен пример действия скрипта Robo, который нажимает кнопку с идентификатором ресурса "com.google.samples.apps.topeka:id/done"
:
{
"eventType": "VIEW_CLICKED",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/done"
}
]
}
Ниже приведен пример действия скрипта Robo, который нажимает на второе вхождение слова "Search"
обнаруженное на экране с помощью OCR:
{
"eventType": "VIEW_CLICKED",
"visionText": "Search",
"matchIndex": 1
}
Ниже приведен пример действия скрипта Robo, который нажимает на элемент экранной клавиатуры с описанием содержимого "Emoji button"
:
{
"eventType": "SOFT_KEYBOARD_CLICK",
"elementDescriptors": [
{
"contentDescription": "Emoji button"
}
]
}
Ниже приведен пример действия скрипта Robo, который нажимает случайные элементы экранной клавиатуры до пяти раз:
{
"eventType": "SOFT_KEYBOARD_RANDOM_CLICK",
"maxNumberOfRuns": 5
}
Отключить программную клавиатуру
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "DISABLE_KEYBOARD" | -- |
Ниже приведен пример действия скрипта Robo, отключающего виртуальную клавиатуру:
{
"eventType": "DISABLE_KEYBOARD"
}
Выполнить команду оболочки adb
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "ADB_SHELL_COMMAND" | -- |
command | Команда оболочки Android Debug Bridge (adb), которую необходимо выполнить. |
Следующий атрибут является необязательным:
-
expectedOutputRegex
— ожидаемый вывод команды в виде регулярного выражения Java. Если вывод не соответствует, действие скрипта Robo завершается ошибкой. По умолчанию это пустая строка, что означает, что вывод не проверяется.
Ниже приведен пример действия скрипта Robo, который очищает данные пользователя тестируемого приложения:
{
"eventType": "ADB_SHELL_COMMAND",
"command": "pm clear __%APP_PACKAGE_NAME%__"
}
Предоставить разрешения
Это действие записывается средством записи скриптов Robo в Android Studio для обеспечения обратной совместимости с средством записи тестов Espresso . Robo-тест предоставляет все разрешения тестируемому приложению в начале каждого сканирования, поэтому это действие не является операцией. НЕ используйте это действие в своих скриптах Robo.
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "PERMISSIONS_REQUEST" | -- |
Игнорировать все элементы на экране
Это действие заставляет Robo игнорировать все элементы на любом экране, который запускает содержащий его сценарий Robo.
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "ALL_ELEMENTS_IGNORED" | -- |
Ниже приведен пример действия скрипта Robo, которое заставляет Robo игнорировать все элементы на экране:
{
"eventType": "ALL_ELEMENTS_IGNORED"
}
Игнорировать элемент
Это действие заставляет Robo игнорировать элемент (или элементы), соответствующие указанным elementDescriptors
.
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "ELEMENT_IGNORED" | -- |
elementDescriptors | Идентифицирует игнорируемые виджеты пользовательского интерфейса, используя иерархию пользовательского интерфейса Android. |
Следующий атрибут является необязательным:
-
ignoreChildren
— если установлено значениеtrue
, Robo также игнорирует все потомки игнорируемых виджетов пользовательского интерфейса. По умолчанию установлено значениеfalse
.
Ниже приведен пример действия скрипта Robo, который заставляет Robo игнорировать все элементы, описания содержимого которых начинаются с "Avatar"
:
{
"eventType": "ELEMENT_IGNORED",
"elementDescriptors": [
{
"contentDescriptionRegex": "Avatar.*"
}
]
}
Введите текст
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
---|---|
eventType | Указывает тип действия скрипта Robo. |
"eventType": "VIEW_TEXT_CHANGED" | Вводит заданный текст в целевой виджет пользовательского интерфейса. |
"eventType": "ENTER_TEXT" | вводит заданный текст в целевой виджет пользовательского интерфейса, а затем отправляет событие KEYCODE_ENTER этому виджету пользовательского интерфейса. |
elementDescriptors | Определяет целевой виджет пользовательского интерфейса с помощью иерархии пользовательского интерфейса Android. |
replacementText | Текст для ввода в целевой виджет пользовательского интерфейса. |
Ниже приведен пример действия скрипта Robo, который вводит "John"
в виджет пользовательского интерфейса с идентификатором ресурса "com.google.samples.apps.topeka:id/first_name"
:
{
"eventType": "VIEW_TEXT_CHANGED",
"replacementText": "John",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/first_name"
}
]
}
Длительный щелчок
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "VIEW_LONG_CLICKED" | -- |
elementDescriptors | Определяет целевой виджет пользовательского интерфейса, используя иерархию пользовательского интерфейса Android. Взаимоисключающее с visionText . |
visionText | Определяет элемент, на котором был сделан долгий щелчок, с помощью OCR. Взаимоисключающее с elementDescriptors . |
matchIndex | Задаёт индекс вхождения совпавшего целевого элемента, если целевой элемент идентифицирован с помощью visionText . Если он равен 0 , действие скрипта Robo выбирает первый совпавший элемент, если он равен 1 , действие скрипта Robo выбирает второй совпавший элемент и т. д. Порядок определяется слева направо, сверху вниз. Значение по умолчанию — 0 (выбирается первое совпадение). |
Следующий атрибут является необязательным:
-
delayTime
— указывает продолжительность нажатия при длинном щелчке в миллисекундах.
Ниже приведен пример действия скрипта Robo, который выполняет пятисекундный щелчок по виджету пользовательского интерфейса с описанием содержимого "Avatar 8"
:
{
"eventType": "VIEW_LONG_CLICKED",
"elementDescriptors": [
{
"contentDescription": "Avatar 8"
}
],
"delayTime": 5000
}
Выполнить одноточечный жест
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
---|---|
"eventType": "ONE_POINT_GESTURE" | -- |
coordinates | Две координаты для одноточечного жеста, отформатированные как «(x1,y1)->(x2,y2)» в процентах или пикселях. |
Следующий атрибут является необязательным:
-
dragAndDrop
— если установлено значениеtrue
, одноточечный жест выполняет действие перетаскивания. По умолчанию установлено значениеfalse
.
Ниже приведен пример одноточечного жеста-действия скрипта Robo, который выполняет смахивание вниз:
{
"eventType": "ONE_POINT_GESTURE",
"coordinates": "(50%,25%)->(50%,75%)"
}
Выполнить двухточечный жест
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
---|---|
"eventType": "TWO_POINT_GESTURE" | -- |
coordinates | Четыре координаты для двухточечного жеста, отформатированные как «(x1,y1)->(x2,y2),(x3,y3)->(x4,y4)» в процентах или пикселях. |
Ниже приведен пример действия скрипта Robo, выполняющего жест разведения пальцев:
{
"eventType": "TWO_POINT_GESTURE",
"coordinates": "(50%,50%)->(25%,50%),(50%,50%)->(75%,50%)"
}
Выполнить действие IME
Это действие нажимает кнопку текущего действия, например, «Далее», «Готово» и «Поиск», в редакторе методов ввода (IME) для указанного целевого виджета пользовательского интерфейса.
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
---|---|
"eventType": "PRESSED_EDITOR_ACTION" | -- |
elementDescriptors | Определяет целевой виджет пользовательского интерфейса с помощью иерархии пользовательского интерфейса Android. |
Ниже приведен пример действия скрипта Robo, который выполняет действие IME для виджета пользовательского интерфейса с идентификатором ресурса "com.google.samples.apps.topeka:id/first_name"
:
{
"eventType": "PRESSED_EDITOR_ACTION",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/first_name"
}
]
}
Нажмите назад
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
eventType | Указывает тип действия скрипта Robo. |
"eventType": "PRESSED_BACK" | Отправляет на устройство событие KEYCODE_BACK . |
"eventType": "PRESSED_BACK_EMULATOR_28" | Используется средством записи скриптов Robo в Android Studio для обратного нажатия на эмуляторы API 28. |
Ниже приведен пример действия скрипта Robo, которое нажимает «назад»:
{
"eventType": "PRESSED_BACK"
}
Пресс-центр
Это действие отправляет на устройство событие KEYCODE_HOME
.
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "GO_HOME" | -- |
Ниже приведен пример действия скрипта Robo, которое приводит к нажатии кнопки «Домой»:
{
"eventType": "GO_HOME"
}
Прокрутите элемент в поле зрения
Это действие заставляет Robo test прокручивать вперед виджет пользовательского интерфейса, соответствующий указанным elementDescriptors
, до тех пор, пока на экране не появится виджет пользовательского интерфейса, соответствующий указанным childElementDescriptors
, или пока прокручиваемый виджет больше не сможет прокручиваться, или пока не будет достигнуто максимальное количество прокруток в 50.
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "ELEMENT_SCROLL_INTO_VIEW" | -- |
elementDescriptors | Идентифицирует прокручиваемый виджет пользовательского интерфейса с помощью иерархии пользовательского интерфейса Android. |
childElementDescriptors | Определяет виджет пользовательского интерфейса для прокрутки с использованием иерархии пользовательского интерфейса Android. |
Ниже приведен пример действия скрипта Robo, который прокручивает виджет пользовательского интерфейса с идентификатором ресурса "my.app.package:id/scrollable_card_container"
до тех пор, пока на экране не появится виджет пользовательского интерфейса с текстом "Orange"
(или пока не станет возможным выполнить больше прокруток, или не будет достигнуто максимальное количество прокруток в 50):
{
"eventType": "ELEMENT_SCROLL_INTO_VIEW",
"elementDescriptors": [
{
"resourceId": "my.app.package:id/scrollable_card_container"
}
],
"childElementDescriptors": [
{
"text": "Orange"
}
]
}
Проведите пальцем
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
---|---|
"eventType": "VIEW_SWIPED" | -- |
swipeDirection | Задает направление смахивания:
|
elementDescriptors | Определяет целевой виджет пользовательского интерфейса с помощью иерархии пользовательского интерфейса Android. |
Ниже приведен пример действия скрипта Robo, который смахивает виджет пользовательского интерфейса с идентификатором ресурса "my.app.package:id/custom_content"
:
{
"eventType": "VIEW_SWIPED",
"swipeDirection": "Up",
"elementDescriptors": [
{
"resourceId": "my.app.package:id/custom_content"
}
]
}
Сделать снимок экрана
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "TAKE_SCREENSHOT" | -- |
screenshotName | Задает имя файла снимка экрана. |
Ниже приведен пример действия скрипта Robo, который делает снимок экрана:
{
"eventType": "TAKE_SCREENSHOT",
"screenshotName": "my_screenshot"
}
Нажмите на точку на экране
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
---|---|
"eventType": "POINT_TAP" | -- |
pointTapXCoordinate | Координата X пикселя точки нажатия. Взаимоисключающее с pointTapXPercent и pointTapYPercent . |
pointTapYCoordinate | Координата Y точки нажатия (в пикселях). Взаимоисключающее с pointTapXPercent и pointTapYPercent . |
pointTapXPercent | Процентная координата X точки касания. Взаимоисключающая с pointTapXCoordinate и pointTapYCoordinate . |
pointTapYPercent | Процентная координата Y точки касания. Взаимоисключающая с pointTapXCoordinate и pointTapYCoordinate . |
Ниже приведен пример действия скрипта Robo, которое нажимает на середину экрана:
{
"eventType": "POINT_TAP",
"pointTapXPercent": 50,
"pointTapYPercent": 50
}
Нажмите на точку внутри элемента
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "POINT_TAP_ELEMENT" | -- |
pointTapXPercent | Процентная координата X внутри целевого элемента. |
pointTapYPercent | Процентная координата Y внутри целевого элемента. |
elementDescriptors | Определяет целевой виджет пользовательского интерфейса с использованием иерархии пользовательского интерфейса Android. |
Ниже приведен пример действия скрипта Robo, который перемещает ползунок полосы прокрутки вправо:
{
"eventType": "POINT_TAP_ELEMENT",
"pointTapXPercent": 80,
"pointTapYPercent": 50,
"elementDescriptors": [
{
"resourceId": "my.app.package:id/my_seekbar"
}
]
}
Прекратить сканирование
Это действие останавливает Robo-тест.
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
---|---|
"eventType": "TERMINATE_CRAWL" | -- |
Ниже приведен пример действия скрипта Robo, которое останавливает тест Robo:
{
"eventType": "TERMINATE_CRAWL"
}
Ждать
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "WAIT" (or "DELAYED_MESSAGE_POSTED") | -- |
delayTime | Указывает продолжительность ожидания в миллисекундах. |
Ниже приведен пример действия скрипта Robo, которое ждет три секунды:
{
"eventType": "WAIT",
"delayTime": 3000
}
Подождите элемент
Это действие заставляет Robo-тест ожидать появления элемента на экране в течение указанного времени ожидания.
В следующей таблице перечислены требуемые атрибуты:
Атрибут | Описание |
"eventType": "WAIT_FOR_ELEMENT" | -- |
delayTime | Указывает время ожидания в миллисекундах. |
elementDescriptors | Идентифицирует ожидаемый виджет пользовательского интерфейса с помощью иерархии пользовательского интерфейса Android. |
Ниже приведен пример действия скрипта Robo, который ожидает до 30 секунд, пока на экране появится виджет пользовательского интерфейса с идентификатором ресурса "my.app.package:id/confirmation_button"
:
{
"eventType": "WAIT_FOR_ELEMENT",
"delayTime": 30000,
"elementDescriptors": [
{
"resourceId": "my.app.package:id/confirmation_button"
}
]
}