В этом документе представлена справочная информация о скриптах Robo, включая их структуру, возможности, использование, запись и действия. Скрипты Robo — это тесты, которые автоматизируют задачи ручного контроля качества (QA) мобильных приложений и позволяют использовать стратегии непрерывной интеграции (CI) и тестирования перед запуском. Скрипт Robo представляет собой JSON-файл, описывающий последовательность действий пользовательского интерфейса (UI) и других действий.
Создать скрипт для робота можно следующими способами:
Воспользуйтесь функцией записи скриптов Robo. (Только для Android)
Создайте скрипт для робота вручную. (Android и iOS+)
Запишите скрипт для робота, а затем отредактируйте его вручную. (Только для 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"
}
]
}
]
Поддержка скриптов Robo на iOS+
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 | Описывает контекст или условие, которое запускает этот скрипт робота. Если опущено, условие запуска этого скрипта робота считается всегда выполненным; другими словами, скрипт робота является безусловным. |
actions | Все действия этого скрипта робота. |
Один файл содержит набор из одного или нескольких скриптов Robo.
Ниже приведён пример файла с двумя безусловными скриптами Robo, каждый из которых содержит одно действие, выполняемое один раз в начале обхода:
[
{
"id": 1000,
"description": "My first Robo script",
"actions": [
{
"eventType": "DISABLE_KEYBOARD"
}
]
},
{
"id": 1001,
"description": "My second Robo script",
"actions": [
{
"eventType": "PRESSED_BACK"
}
]
}
]
Дескриптор контекста
Дескриптор контекста определяет контекст или условие, запускающее скрипт робота, используя один или несколько атрибутов:
| Атрибут | Описание |
|---|---|
"condition": "always" | Всегда запускает скрипт робота. |
"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"
}
]
}
Ниже приведён пример скрипта для робота, который ждёт 5 секунд после каждого действия робота, не являющегося скриптом:
{
"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, указывающий параметры выполнения этого скрипта. Этот заголовок конфигурации начинается с ключевого слова roboscript , за которым следует JSON-представление желаемых параметров выполнения.
Скрипты для роботов поддерживают следующие параметры выполнения:
-
executionMode— параметры выполнения, применяемые при запуске скрипта Robo:-
strict— если установлено значениеtrue, скрипт Robo не использует частичное совпадение, пропуск текущего действия и приостановку . То есть скрипт Robo выполняется как обычный инструментальный тест и завершается с ошибкой, как только какое-либо из его действий не может быть выполнено. По умолчанию значение равноfalse. -
dismiss_popups— если установлено значениеtrue, тест Robo закрывает любые неожиданные диалоговые окна во время выполнения скрипта Robo, даже вstrictрежиме. Этот параметр не оказывает никакого эффекта, если режим неstrict. По умолчанию он имеетfalse. -
notify— если установлено значениеfalse, скрипт Robo не будет отображать уведомления на экране в начале и в конце своего выполнения. По умолчанию значение равноtrue.
-
-
postscript— параметры выполнения, применяемые после завершения скрипта Robo:-
terminate- если установлено значениеtrue, Robo test прекращает сканирование после завершения работы скрипта Robo. По умолчанию значениеfalse.
-
Ниже приведён пример скрипта Robo, выполняемого в strict режиме без экранных уведомлений, который ждёт три секунды, после чего сканирование останавливается:
"roboscript": {
"executionMode": {
"strict": true,
"notify": false
},
"postscript": {
"terminate": true
}
}
[
{
"eventType": "WAIT",
"delayTime": 3000
}
]
Параметры шаблона
Параметр шаблона — это заполнитель в скрипте Robo, который заменяется фактическим значением, когда Robo Test загружает этот скрипт для выполнения. Параметры шаблона начинаются с двойного подчеркивания, за которым следует знак процента, а заканчиваются знаком процента, за которым следует двойное подчеркивание.
Скрипты для роботов поддерживают следующий параметр шаблона:
-
__%APP_PACKAGE_NAME%__- имя пакета тестируемого приложения.
Ниже приведён пример скрипта Robo, который останавливает процесс тестирования приложения:
[
{
"eventType": "ADB_SHELL_COMMAND",
"command": "am force-stop __%APP_PACKAGE_NAME%__"
}
]
Комментарии
В скрипте Robo могут содержаться комментарии, которые начинаются с символов # или // .
Ниже приведён пример скрипта для робота с несколькими комментариями:
# Confirm a user account.
[
{
// Click the DONE button.
"eventType": "VIEW_CLICKED",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/done"
}
]
}
]
Возможности
По умолчанию, пока все действия скрипта Robo не будут завершены (или хотя бы предприняты), скрипт Robo остается активным. Robo test постоянно пытается сопоставить действие скрипта Robo всякий раз, когда выбирает действие для выполнения. Для повышения надежности скрипт Robo использует следующие методы:
| Техника | Описание |
| Частичное совпадение | Если текущее действие скрипта Robo не может быть полностью сопоставлено, критерии сопоставления ослабляются, и попытка сопоставления повторяется. Частичное сопоставление не учитывает дескриптор самого внешнего элемента при сопоставлении целевого виджета пользовательского интерфейса действия скрипта Robo. Если частичное совпадение удается, соответствующее действие скрипта Robo выполняется как обычно. Этот метод поддерживает сценарии, в которых структура приложения изменяется, например, между версиями приложения, когда происходит перестановка элементов экрана. |
| Пропустить текущее действие | Если текущее действие скрипта Robo не может быть полностью или частично сопоставлено, Robo пытается сопоставить следующее действие скрипта Robo. Если последующее действие полностью или частично совпадает, проверка Robo пропускает (и никогда не возвращается к) текущее действие скрипта Robo и выполняет последующее. Этот метод поддерживает сценарии, когда поведение приложения меняется между версиями или является нестабильным, например, когда диалоговое окно может появляться на разных экранах во время записи и воспроизведения скрипта Robo. |
| Приостановить | Если ни текущее, ни последующие действия скрипта Robo не могут быть полностью или частично сопоставлены, выполнение скрипта Robo временно приостанавливается, и Robo test выбирает действие для выполнения, используя другие свои стратегии. После завершения этого действия Robo test возобновляет выполнение скрипта 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 script 3"как последний подходящий скрипт робота.
Повторные запуски
По умолчанию Robo запускает скрипт Robo не более одного раза за время сканирования. Это можно настроить с помощью атрибута maxNumberOfRuns .
Ниже приведён пример скрипта Robo, который переводит тестируемое приложение в фоновый режим до 10 раз:
{
"id": 1000,
"maxNumberOfRuns": 10,
"contextDescriptor": {
"condition": "app_under_test_shown"
},
"actions": [
{
"eventType": "GO_HOME"
}
]
}
Этап ползания
Робо-скрипты применимы на разных этапах выполнения роботизированного обхода:
| Этап ползания | Описание |
pre_crawl | Перед запуском Robo и началом сканирования тестируемого приложения. |
post_crawl | После завершения сканирования тестируемого приложения программой Robo, продолжительность скрипта post_crawl не должна превышать 15 секунд, иначе сканирование может завершиться по истечении времени ожидания. |
crawl | Основной этап сканирования, когда Robo сканирует тестируемое приложение. |
close_screen | Когда робот пытается вернуться назад (откатиться назад) с заданного экрана, после того как были проверены все возможные действия на этом экране, по умолчанию он нажимает кнопку «Назад», что нежелательно в некоторых сценариях. |
Если атрибут crawlStage скрипта Robo не указан, подразумевается, что он имеет значение crawl .
Ниже приведён пример скрипта 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 соответствует экрану во время обхода 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 test гарантирует, что соответствующий дочерний элемент отобразится на экране посредством действия позиционирования содержащего его RecyclerView или AdapterView.
В ходе роботизированного тестирования записанное действие выполняется непосредственно на дочернем элементе, поскольку он уже отображается на экране.
Ниже приведён пример действия клика по дочернему элементу 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
}
]
}
Запишите скрипт для робота в Android Studio и запустите его в Test Lab
В Android Studio можно создать скрипт Robo, который сохранит скрипт в виде JSON-файла. Затем этот JSON-файл можно загрузить в Firebase Test Lab вместе с приложением и запустить соответствующие тесты.
При запуске роботизированного теста с прикрепленным скриптом, роботизированный тест сначала выполняет предварительно запрограммированные действия, а затем, как обычно, исследует приложение.
Чтобы создать JSON-файл с скриптом робота в Android Studio, выполните действия, описанные в разделе «Запись скрипта робота с помощью Test Lab в Android Studio» .
Действия скрипта робота
Следующий общий необязательный атрибут применяется ко всем действиям:
-
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 Test Recorder . Robo test предоставляет все разрешения тестируемому приложению в начале каждого обхода, поэтому это действие ничего не меняет. НЕ используйте это действие в своих скриптах 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"
}
]
}
Прекратить ползание
Это действие останавливает тестирование робота.
В следующей таблице перечислены необходимые атрибуты:
| Атрибут | Описание |
|---|---|
"eventType": "TERMINATE_CRAWL" | -- |
Ниже приведён пример действия скрипта Robo, которое останавливает тестирование Robo:
{
"eventType": "TERMINATE_CRAWL"
}
Ждать
В следующей таблице перечислены необходимые атрибуты:
| Атрибут | Описание |
"eventType": "WAIT" (or "DELAYED_MESSAGE_POSTED") | -- |
delayTime | Указывает, сколько времени нужно подождать, в миллисекундах. |
Ниже приведён пример действия скрипта Robo, которое ждёт три секунды:
{
"eventType": "WAIT",
"delayTime": 3000
}
Дождитесь появления элемента
Это действие заставляет Robo test ждать появления элемента на экране в течение указанного времени ожидания.
В следующей таблице перечислены необходимые атрибуты:
| Атрибут | Описание |
"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"
}
]
}