本文檔提供有關 Robo 腳本的參考信息,包括結構、功能、用法、記錄和操作。 Robo 腳本是自動執行移動應用程序的手動質量保證 (QA) 任務的測試,並支持持續集成 (CI) 和發布前測試策略。 Robo 腳本是一個 JSON 文件,描述一系列用戶界面 (UI) 和其他操作。
您可以通過以下方式創建 Robo 腳本:
使用 Robo 腳本錄製功能。 (僅限安卓)
手動創建 Robo 腳本。 (安卓和iOS+)
錄製 Robo 腳本,然後手動編輯。 (僅限安卓)
要了解有關使用 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 腳本的支持
iOS+ 版 Robo(測試版)對 Robo 腳本的支持有限。 iOS+ 的 Robo 腳本語法與 Android 語法相同,並且支持的 iOS+ 功能的行為與 Android 對應功能類似。
iOS+ 支持以下操作:
- 斷言
- 點擊
- 長按
- 滑動
- 忽略所有元素
- 等待
- 截圖
- 終止抓取
iOS+ 支持元素描述符中的以下標識屬性:
- 班級名稱
- 祖先類名
- 內容描述(和正則表達式)
- 文本(和正則表達式)
iOS+ 支持上下文描述符中的以下觸發條件:
- 顯示正在測試的應用程序
- 元素存在
- 執行的非 Robo 腳本操作
結構
Robo 腳本有幾個屬性來描述 Robo 如何執行它。大多數這些屬性都是可選的,具有預定義的默認值:
屬性 | 描述 |
id | 一個整數,有助於在爬網輸出中跟踪此 Robo 腳本。 |
description | 與id 類似,但更具描述性。 |
crawlStage | 爬行 Robo 的階段應用此 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": "element_present" | 檢查屏幕上是否存在與elementDescriptors 或由visionText 指定的文本相匹配的 UI 小部件。 |
"condition": "element_disabled" | 檢查屏幕上是否存在與elementDescriptors 匹配的 UI 小部件,並且無法與之交互。 |
"condition": "element_checked" | 檢查屏幕上是否存在與elementDescriptors 匹配的 UI 小部件並已檢查。 |
"condition": "app_under_test_shown" | 檢查被測應用程序是否在前台運行。 |
"condition": "default_launcher_shown" | 檢查是否顯示設備的主屏幕,這意味著沒有應用程序在前台運行。 |
"condition": "non_roboscript_action_performed" | 檢查 Robo 測試執行的最後一個nonRoboscriptActionCount 連續操作是否不是 Robo 腳本操作。 |
negateCondition | 如果設置為true ,則否定condition 。例如,您可以使用此屬性來檢查屏幕上是否不存在 UI 小部件,或者測試中的應用程序是否未在前台運行。 |
elementDescriptors | 一個或多個元素描述符,用於標識屏幕上的 UI 小部件。它與element_present 、 element_disabled 和element_checked 條件結合使用。與visionText 互斥。有關詳細信息,請參閱元素描述符。 |
visionText | 使用光學字符識別 (OCR) API 檢測屏幕上的文本。 visionText 與element_present 條件結合使用。與elementDescriptors 互斥。 |
nonRoboscriptActionCount | 之前執行的連續非 Robo 腳本操作的數量。它與non_roboscript_action_performed 條件結合使用,在每個nonRoboscriptActionCount Robo 操作後觸發 Robo 腳本。默認情況下,它是1 。 |
以下是由屏幕上顯示資源 ID "my.app.package:id/page_header"
的 UI 小部件觸發的 Robo 腳本示例:
{
"id": 1000,
"contextDescriptor": {
"condition": "element_present",
"elementDescriptors": [
{
"resourceId": "my.app.package:id/page_header"
}
]
},
"actions": [
{
"eventType": "VIEW_CLICKED",
"elementDescriptors": [
{
"text": "Settings"
}
]
}
]
}
以下是由光學字符識別 (OCR) 檢測到的"Privacy Policy"
觸發的 Robo 腳本示例:
{
"id": 1000,
"description": "Vision text Robo script",
"contextDescriptor": {
"condition": "element_present",
"visionText": "Privacy Policy"
},
"actions": [
{
"eventType": "VIEW_CLICKED",
"visionText": "Privacy Policy"
}
]
}
以下是 Robo 腳本的示例,該腳本在每個非腳本 Robo 操作後等待 5 秒:
{
"contextDescriptor": {
"condition": "non_roboscript_action_performed"
},
"maxNumberOfRuns" : 1000,
"actions" : [
{
"eventType" : "DELAYED_MESSAGE_POSTED",
"delayTime" : 5000
}]
}
行動
Robo 腳本中的每個操作都表示為一組一個或多個屬性值對,如下表所述:
屬性 | 描述 |
eventType | 指定操作的類型,例如單擊、文本編輯等。每個操作都需要。 |
elementDescriptors | 標識 UI 小部件的描述符。對於具有目標 UI 小部件的所有操作都是必需的,例如單擊特定按鈕。 |
optional | 如果設置為true ,則在無法執行此操作時將跳過該操作。例如,當它在屏幕上找不到其目標 UI 小部件時,會跳過此操作,而不會導致包含的 Robo 腳本失敗。默認情況下,該值為false 。 |
replacementText | 要輸入到目標 UI 小部件中的文本。文本編輯操作所需。 |
swipeDirection | 指定滑動的方向。滑動操作所需。 |
delayTime | 指定等待的時間(以毫秒為單位)。等待操作所需。 |
pointTapXCoordinate 和pointTapYCoordinate | 點擊點的像素 X 和 Y 坐標。與pointTapXPercent 和pointTapYPercent 互斥。點按操作所需。 |
pointTapXPercent 和pointTapYPercent | 點擊點的百分比 X 和 Y 坐標。與pointTapXCoordinate 和pointTapYCoordinate 互斥。點按操作所需。 |
以下是 Robo 腳本的示例,其中包含兩個沒有目標 UI 小部件的操作,這意味著這些操作不在特定 UI 小部件上運行:
[
{
"eventType": "DELAYED_MESSAGE_POSTED",
"delayTime": 3000
},
{
"eventType": "PRESSED_BACK"
}
]
元素描述符
元素描述符使用以下一個或多個標識屬性來標識 UI 小部件:
屬性 | 描述 |
className | – |
ancestorClassName | 元素的 UI 層次結構祖先的類名稱。祖先是元素的 UI 層次結構中的任何父節點,包括元素本身。 |
resourceId | – |
resourceIdRegex | 用於匹配resourceId 的Java正則表達式。 |
contentDescription | – |
contentDescriptionRegex | 用於匹配contentDescription 的 Java 正則表達式。 |
text (出現在屏幕上) | – |
textRegex | Java正則表達式來匹配text 。 |
groupViewChildPosition 、 recyclerViewChildPosition 或adapterViewChildPosition | 表示 UI 小部件的子位置,具體取決於其父小部件的類型。 |
通常,這些屬性是未定義的,例如,按鈕可能沒有文本和內容描述。即使存在某些屬性值,它們在給定應用程序屏幕上也可能不是唯一的(包括resourceId
)。
例如,通常只能通過使用其父窗口小部件中的不同子位置來區分列表中的項目。這意味著僅使用一個元素描述符來標識 UI 小部件通常是不夠的。因此,操作的elementDescriptors
屬性包含一系列元素描述符,這些元素描述符經過排序,第一個對應於目標 UI 小部件,第二個對應於目標 UI 小部件的父小部件,依此類推。當操作的目標 UI 小部件的所有元素描述符與相應的 UI 小部件子層次結構匹配時,該操作的目標 UI 小部件就會匹配。
以下是具有文本更改和單擊操作的 Robo 腳本示例,這兩個操作都要求您使用提供的元素描述符來識別目標 UI 小部件:
[
{
"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"
}
]
}
]
執行選項
您可以選擇使用 JSON 對象為 Robo 腳本中的操作列表添加前綴,該對象指定該 Robo 腳本的執行選項。此配置標頭以roboscript
關鍵字開頭,後跟所需執行選項的 JSON 表示形式。
Robo 腳本支持以下執行選項:
-
executionMode
- Robo 腳本運行時應用的執行選項:-
strict
- 如果設置為true
,Robo 腳本不會採用部分匹配、跳過當前操作和中止。也就是說,Robo 腳本作為常規儀器測試執行,一旦無法執行任何操作就會失敗。 -
notify
- 如果設置為false
,Robo 腳本在執行開始和結束時不會顯示屏幕通知。默認情況下,它是true
。
-
-
postscript
- Robo 腳本完成後應用的執行選項:-
terminate
- 如果設置為true
,Robo 測試將在 Robo 腳本完成後停止爬行。
-
以下是在strict
模式下執行的 Robo 腳本示例,沒有屏幕通知,該腳本會休眠三秒鐘,然後爬網停止:
"roboscript": {
"executionMode": {
"strict": true,
"notify": false
},
"postscript": {
"terminate": true
}
}
[
{
"eventType": "DELAYED_MESSAGE_POSTED",
"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 腳本操作的目標 UI 小部件時不考慮最外層元素描述符。 如果部分匹配成功,則照常執行相應的 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": "DELAYED_MESSAGE_POSTED",
"delayTime": 3000
}
]
},
{
"id": 1001,
"description": "Robo script 2",
"priority": "2",
"contextDescriptor": {
"condition": "app_under_test_shown"
},
"actions": [
{
"eventType": "DELAYED_MESSAGE_POSTED",
"delayTime": 3000
}
]
},
{
"id": 1002,
"description": "Robo script 3",
"contextDescriptor": {
"condition": "app_under_test_shown"
},
"actions": [
{
"eventType": "DELAYED_MESSAGE_POSTED",
"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 腳本適用於給定 Robo 爬行的不同階段:
爬行階段 | 描述 |
pre_crawl | 在 Robo 啟動並開始抓取測試中的應用程序之前。 |
post_crawl | Robo 完成對被測應用程序的爬行後。 |
crawl | 主要爬行階段,Robo 爬行測試中的應用程序。 |
close_screen | 當 Robo 嘗試從給定屏幕返回(回溯)時,當探索該屏幕上的所有可能操作時。默認情況下,Robo 會按回鍵,這在某些情況下是不可取的。 |
如果 Robo 腳本的crawlStage
屬性未指定,則隱含為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 | 觸發此條件操作的上下文/條件。它具有與 [Robo 腳本的 contextDescriptor](#context-descriptor) 相同的結構並提供類似的功能。 |
觸發後,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": "DELAYED_MESSAGE_POSTED",
"delayTime": 10000
},
{
"description": "Screen on",
"eventType": "ADB_SHELL_COMMAND",
"command": "input keyevent 82"
},
{
"description": "Wait for 10 seconds",
"eventType": "DELAYED_MESSAGE_POSTED",
"delayTime": 10000
}
}
忽略動作
Robo 腳本可以包含讓 Robo 忽略特定屏幕上的特定 UI 小部件或所有 UI 小部件的指令。這些指令表示為忽略相應的eventType
ELEMENT_IGNORED
和ALL_ELEMENTS_IGNORED
的“操作”。
每當包含忽略操作的 Robo 腳本的contextDescriptor
屬性與給定屏幕匹配時,Robo 不會與其忽略操作所針對的任何UI 小部件交互(除非某些其他Robo 腳本操作使Robo 對被忽略的UI 小部件之一執行操作)。
Robo 腳本可以包含忽略、條件和非條件操作的混合。與其他 Robo 腳本操作不同,只要包含 Robo 腳本的contextDescriptor
與 Robo 爬網期間的屏幕匹配,就會應用忽略操作,無論priority
和maxNumberOfRuns
屬性的值如何。
以下是包含兩個 Robo 腳本的文件示例。第一個 Robo 腳本使 Robo 忽略屏幕上包含資源 ID 為"my.app.package:id/ignored_screen"
的 UI 小部件的所有 UI 小部件。第二個 Robo 腳本使 Robo 忽略資源 ID 與資源 ID 為"my.app.package:id/main_screen"
UI 小部件的屏幕上的 Java 正則表達式".*:id/done"
/done”匹配的UI 小部件:
[
{
"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 腳本捕獲作為 Robo 腳本操作目標的 RecyclerView 子級的絕對數據位置作為recyclerViewChildPosition
。 Robo 腳本還捕獲作為 Robo 腳本操作目標的 AdapterView 子級的絕對數據位置作為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
}
]
}
在 Android Studio 中錄製 Robo 腳本並在測試實驗室中運行
您可以在 Android Studio 中創建 Robo 腳本,該腳本會將腳本保存為 JSON 文件。然後,您可以將 JSON 文件與應用程序一起上傳到 Firebase 測試實驗室並相應地運行測試。
當您運行附加腳本的 Robo 測試時,Robo 測試首先執行預先編寫腳本的操作,然後像往常一樣探索應用程序。
要在 Android Studio 中創建 Robo 腳本 JSON 文件,請按照使用 Android Studio 中的測試實驗室記錄 Robo 腳本中的步驟進行操作。
Robo 腳本動作
以下公共可選屬性適用於所有操作:
-
description
- 幫助跟踪 Robo 測試輸出中此 Robo 腳本操作的執行情況。
斷言
如果斷言條件為真,Robo 腳本將繼續執行下一個操作,這可能是另一個斷言。否則,Robo 腳本執行將因斷言失敗而停止。
下表列出了所需的屬性:
屬性 | 描述 |
"eventType": "ASSERTION" | -- |
contextDescriptor | 描述斷言的上下文或條件。它具有與Robo 腳本的 contextDescriptor相同的結構並提供類似的功能。 |
以下是 Robo 腳本斷言的示例,用於檢查被測應用程序是否位於前台:
{
"eventType": "ASSERTION",
"contextDescriptor": {
"condition": "app_under_test_shown"
}
}
以下是 Robo 腳本斷言的示例,用於檢查屏幕上是否存在資源 ID 為"com.google.samples.apps.topeka:id/done"
的 UI 小部件:
{
"eventType": "ASSERTION",
"contextDescriptor": {
"condition": "element_present",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/done"
}
]
}
}
以下是 Robo 腳本斷言的示例,該斷言使用 OCR 檢查屏幕上是否未檢測到"Settings"
:
{
"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" | 由 Android Studio 中的 Robo 腳本記錄器用於單擊列表項。 |
elementDescriptors | 使用 Android UI 層次結構識別單擊的 UI 小部件。與visionText 互斥。 |
visionText | 使用 OCR 識別單擊的元素。與elementDescriptors 互斥。 |
maxNumberOfRuns | 指定當eventType 為SOFT_KEYBOARD_RANDOM_CLICK 時,單擊軟鍵盤隨機元素的次數。默認值為1 。 |
以下是 Robo 腳本操作的示例,該操作單擊資源 ID 為"com.google.samples.apps.topeka:id/done"
的按鈕:
{
"eventType": "VIEW_CLICKED",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/done"
}
]
}
以下是 Robo 腳本操作的示例,該操作單擊使用 OCR 在屏幕上檢測到的"Privacy Policy"
:
{
"eventType": "VIEW_CLICKED",
"visionText": "Privacy Policy"
}
以下是 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 shell命令
下表列出了所需的屬性:
屬性 | 描述 |
"eventType": "ADB_SHELL_COMMAND" | -- |
command | 要執行的 Android 調試橋 (adb) shell 命令。 |
以下屬性是可選的:
-
expectedOutputRegex
- 作為 Java 正則表達式的命令的預期輸出。如果輸出不匹配,Robo 腳本操作將失敗。默認情況下,它是一個空字符串,這意味著不檢查輸出。
以下是清除測試中的應用程序用戶數據的 Robo 腳本操作示例:
{
"eventType": "ADB_SHELL_COMMAND",
"command": "pm clear __%APP_PACKAGE_NAME%__"
}
授予權限
此操作由 Android Studio 中的 Robo 腳本記錄器記錄,以便向後兼容Espresso Test Recorder 。 Robo 測試在每次爬網開始時向被測應用程序授予所有權限,因此,此操作是無操作。不要在您的 Robo 腳本中使用此操作。
下表列出了所需的屬性:
屬性 | 描述 |
"eventType": "PERMISSIONS_REQUEST" | -- |
忽略屏幕上的所有元素
此操作使 Robo 忽略任何屏幕上觸發包含 Robo 腳本的所有元素。
下表列出了所需的屬性:
屬性 | 描述 |
"eventType": "ALL_ELEMENTS_IGNORED" | -- |
以下是 Robo 腳本操作的示例,該操作使 Robo 忽略屏幕上的所有元素:
{
"eventType": "ALL_ELEMENTS_IGNORED"
}
忽略一個元素
此操作使 Robo 忽略與指定的elementDescriptors
匹配的一個或多個元素。
下表列出了所需的屬性:
屬性 | 描述 |
"eventType": "ELEMENT_IGNORED" | -- |
elementDescriptors | 使用 Android UI 層次結構識別被忽略的 UI 小部件。 |
以下屬性是可選的:
-
ignoreChildren
- 如果設置為true
,Robo 還會忽略被忽略的 UI 小部件的所有後代。默認情況下,它是false
。
以下是 Robo 腳本操作的示例,該操作使 Robo 忽略所有內容描述以"Avatar"
開頭的元素:
{
"eventType": "ELEMENT_IGNORED",
"elementDescriptors": [
{
"contentDescriptionRegex": "Avatar.*"
}
]
}
輸入文本
下表列出了所需的屬性:
屬性 | 描述 |
---|---|
eventType | 指定 Robo 腳本操作的類型。 |
"eventType": "VIEW_TEXT_CHANGED" | 將給定文本輸入到目標 UI 小部件中。 |
"eventType": "ENTER_TEXT" | 將給定文本輸入到目標 UI 小部件中,然後將KEYCODE_ENTER 事件發送到此 UI 小部件。 |
elementDescriptors | 使用 Android UI 層次結構標識目標 UI 小部件。 |
replacementText | 要輸入到目標 UI 小部件中的文本。 |
以下是 Robo 腳本操作的示例,該操作將"John"
輸入到資源 ID 為"com.google.samples.apps.topeka:id/first_name"
UI 小部件中:
{
"eventType": "VIEW_TEXT_CHANGED",
"replacementText": "John",
"elementDescriptors": [
{
"resourceId": "com.google.samples.apps.topeka:id/first_name"
}
]
}
長按
下表列出了所需的屬性:
屬性 | 描述 |
"eventType": "VIEW_LONG_CLICKED" | -- |
elementDescriptors | 使用 Android UI 層次結構標識目標 UI 小部件。與visionText 互斥。 |
visionText | 使用 OCR 識別長按的元素。與elementDescriptors 互斥。 |
以下屬性是可選的:
-
delayTime
- 指定長按的持續時間(以毫秒為單位)。
以下是 Robo 腳本操作的示例,該操作對內容描述為"Avatar 8"
UI 小部件執行五秒長的單擊:
{
"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 操作
此操作會按下指定目標 UI 小部件的輸入法編輯器 (IME) 上的當前操作按鈕,例如“下一步”、“完成”和“搜索”。
下表列出了所需的屬性:
屬性 | 描述 |
---|---|
"eventType": "PRESSED_EDITOR_ACTION" | -- |
elementDescriptors | 使用 Android UI 層次結構標識目標 UI 小部件。 |
以下是 Robo 腳本操作的示例,該操作對資源 ID 為"com.google.samples.apps.topeka:id/first_name"
UI 小部件執行 IME 操作:
{
"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" | 由 Android Studio 中的 Robo 腳本記錄器用於壓回模擬器 API 28。 |
以下是按回鍵的 Robo 腳本操作示例:
{
"eventType": "PRESSED_BACK"
}
按首頁
此操作將KEYCODE_HOME
事件發送到設備。
下表列出了所需的屬性:
屬性 | 描述 |
"eventType": "GO_HOME" | -- |
以下是按 Home 鍵的 Robo 腳本操作示例:
{
"eventType": "GO_HOME"
}
將元素滾動到視圖中
此操作使 Robo 測試向前滾動與指定的elementDescriptors
匹配的 UI 小部件,直到屏幕上出現與指定的childElementDescriptors
匹配的 UI 小部件,或者滾動的小部件無法再滾動,或者達到最大滾動次數 50。
下表列出了所需的屬性:
屬性 | 描述 |
"eventType": "ELEMENT_SCROLL_INTO_VIEW" | -- |
elementDescriptors | 使用 Android UI 層次結構標識滾動的 UI 小部件。 |
childElementDescriptors | 使用 Android UI 層次結構標識要滾動到的 UI 小部件。 |
以下是 Robo 腳本操作的示例,該操作滾動具有資源 ID "my.app.package:id/scrollable_card_container"
的 UI 小部件,直到屏幕上出現帶有文本"Orange"
的 UI 小部件(或者無法再滾動)執行,或達到最大滾動次數50):
{
"eventType": "ELEMENT_SCROLL_INTO_VIEW",
"elementDescriptors": [
{
"resourceId": "my.app.package:id/scrollable_card_container"
}
],
"childElementDescriptors": [
{
"text": "Orange"
}
]
}
滑動
下表列出了所需的屬性:
屬性 | 描述 |
---|---|
"eventType": "VIEW_SWIPED" | -- |
swipeDirection | 指定滑動方向:
|
elementDescriptors | 使用 Android UI 層次結構標識目標 UI 小部件。 |
以下是 Robo 腳本操作的示例,該操作向上滑動資源 ID 為"my.app.package:id/custom_content"
的 UI 小部件:
{
"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 UI 層次結構標識目標 UI 小部件。 |
以下是將搜索欄的滑塊向右移動的 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": "DELAYED_MESSAGE_POSTED" | -- |
delayTime | 指定等待的時間(以毫秒為單位)。 |
以下是等待三秒的 Robo 腳本操作示例:
{
"eventType": "DELAYED_MESSAGE_POSTED",
"delayTime": 3000
}
等待一個元素
此操作使 Robo 測試等待元素出現在屏幕上直至指定的超時時間。
下表列出了所需的屬性:
屬性 | 描述 |
"eventType": "WAIT_FOR_ELEMENT" | -- |
delayTime | 指定等待超時,以毫秒為單位。 |
elementDescriptors | 使用 Android UI 層次結構標識等待的 UI 小部件。 |
以下是 Robo 腳本操作的示例,該操作最多等待 30 秒,以便資源 ID 為"my.app.package:id/confirmation_button"
UI 小部件出現在屏幕上:
{
"eventType": "WAIT_FOR_ELEMENT",
"delayTime": 30000,
"elementDescriptors": [
{
"resourceId": "my.app.package:id/confirmation_button"
}
]
}