Robo 指令碼參考指南

這份文件提供有關 Robo 指令碼的參考資訊,包括結構、功能、用途、錄製和動作。Robo 指令碼是測試,可自動執行行動應用程式的手動品質保證 (QA) 工作,並啟用持續整合 (CI) 和發布前測試策略。Robo 腳本是 JSON 檔案,用於描述使用者介面 (UI) 和其他動作的序列。

您可以透過下列方式建立 Robo 指令碼:

  • 使用 Robo 指令碼記錄功能。(僅限 Android 裝置)

  • 手動建立 Robo 指令碼。(Android 和 iOS+)

  • 錄製 Robo 指令碼,然後手動編輯。(僅限 Android 裝置)

如要進一步瞭解如何使用 Robo 指令碼,請參閱「執行 Robo 指令碼」。

簡介

Robo 指令碼會連同其他輸入內容 (例如受測應用程式的 Android 應用程式套件 (APK)) 一併提供給 Robo 測試。

以下是 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 指令碼,且具有預設的觸發條件 (如上例所示),則可以使用較簡單的格式指定檔案中的 Robo 指令碼,也就是以動作序列的形式:app_under_test_shown

[
  {
    "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 (Beta 版) 僅支援部分 Robo 指令碼。iOS+ 的 Robo 指令碼語法與 Android 語法相同,且支援的 iOS+ 功能與 Android 對應功能類似。

iOS+ 支援下列動作:

  • 斷言
  • 點按
  • 長按
  • 滑動
  • 忽略所有元素
  • 等待
  • 擷取螢幕截圖
  • 終止檢索

iOS+ 支援元素描述元中的下列識別屬性:

  • 課程名稱
  • 祖先類別名稱
  • 內容說明 (和規則運算式)
  • 文字 (和規則運算式)

iOS+ 支援下列情境描述元中的觸發條件

  • 顯示受測應用程式
  • 元素存在
  • 執行非 Robo 指令碼動作

結構

Robo 指令碼有幾個屬性,用於說明 Robo 如何執行指令碼。大多數屬性都是選用屬性,且預先定義了預設值:

屬性 說明
id 有助於在檢索輸出內容中追蹤這個 Robo 指令碼的整數。Robo 內建 Robo 指令碼,並有自己的 id。雖然不同 Robo 指令碼中的 id 不會影響其行為,但要從檢索輸出內容中區分這些 Robo 指令碼的動作可能很困難。建議為 Robo 指令碼指派 id 1000 以上的專屬值,以免發生衝突。
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": "always" 一律會觸發 Robo 指令碼。
"condition": "element_present" 檢查畫面上是否有符合 elementDescriptorsvisionText 指定文字的 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_presentelement_disabledelement_checked 條件搭配使用。與 visionText 互斥。詳情請參閱「元素描述元」。
visionText 系統會使用光學字元辨識 (OCR) API 偵測畫面上的文字。visionText 會與 element_present 條件搭配使用。與 elementDescriptors 互斥。
nonRoboscriptActionCount 先前執行的連續非 Robo 指令碼動作數量。這項條件會與 non_roboscript_action_performed 條件搭配使用,在每次 nonRoboscriptActionCount Robo 動作後觸發 Robo 指令碼。預設值為 1

以下是 Robo 指令碼範例,當畫面上出現資源 ID 為 "my.app.package:id/page_header" 的 UI 小工具時,系統就會觸發該指令碼:

{
  "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" : "WAIT",
      "delayTime" : 5000
    }]
}

動作

Robo 指令碼中的每個動作都以一或多個屬性值配對的組合表示,如下表所示:

屬性 說明
eventType 指定動作類型,例如點擊、編輯文字等。每個動作都必須提供這項資訊。
elementDescriptors 可識別 UI 小工具的描述元。所有有目標 UI 小工具的動作都必須使用這個屬性,例如點選特定按鈕。
optional 如果設為 true,系統無法執行這項動作時就會略過。舉例來說,如果系統在畫面上找不到目標 UI 小工具,就會略過這項動作,但不會導致包含的 Robo 腳本失敗。預設值為 false
replacementText 要輸入目標 UI 小工具的文字。文字編輯動作的必要條件。
swipeDirection 指定滑動方向。滑動動作必須使用這類元素。
delayTime 指定等待時間長度 (以毫秒為單位)。等待動作的必要條件。
pointTapXCoordinatepointTapYCoordinate 觸碰點的像素 X 和 Y 座標。與 pointTapXPercentpointTapYPercent 互斥。點選動作必須使用這類元素。
pointTapXPercentpointTapYPercent 觸碰點的 X 和 Y 座標百分比。與 pointTapXCoordinatepointTapYCoordinate 互斥。點選動作必須使用這類元素。

以下是 Robo 指令碼範例,其中包含兩個沒有目標 UI 小工具的動作,也就是說,這些動作不會對特定 UI 小工具執行操作:

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

元素描述元

元素描述元會使用下列一或多個識別屬性,識別 UI 小工具:

屬性 說明
className
ancestorClassName 元素 UI 階層祖項的類別名稱。祖先是元素 UI 階層中的任何父項節點,包括元素本身。
resourceId
resourceIdRegex 用於比對 resourceId 的 Java 規則運算式。
contentDescription
contentDescriptionRegex 用於比對 contentDescription 的 Java 規則運算式。
text (畫面顯示的內容)
textRegex 用於比對 text 的 Java 規則運算式。
groupViewChildPositionrecyclerViewChildPositionadapterViewChildPosition Represents a UI widget's child position depending on the kind of its parent widget.

這些屬性通常未定義,例如按鈕可能沒有文字和內容說明。即使存在某些屬性值,這些值在特定應用程式畫面 (包括 resourceId) 上可能不是唯一值。

舉例來說,一般來說,只有在父項小工具中使用不同的子項位置,才能區分清單中的項目。也就是說,通常只使用一個元素描述元來識別 UI 小工具是不夠的。因此,動作的 elementDescriptors 屬性包含一系列元素描述元,這些描述元依序對應至目標 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"
      }
    ]
  }
]

執行作業選項

您可以選擇在 Robo 指令碼的動作清單中,加上指定該 Robo 指令碼執行選項的 JSON 物件前置字元。這個設定標頭以 roboscript 關鍵字開頭,後面接著所需執行選項的 JSON 表示法。

Robo 指令碼支援下列執行選項:

  • executionMode:執行 Robo 指令碼時套用的執行選項:
    • strict - 如果設為 true,Robo 指令碼不會採用部分相符項目,並會略過目前動作和暫停。也就是說,系統會將 Robo 指令碼視為一般檢測測試執行,只要有任何動作無法執行,測試就會失敗。預設值為 false
    • dismiss_popups - 如果設為 true,即使在 strict 模式下執行 Robo 指令碼,Robo 測試也會關閉任何非預期的對話方塊。如果不是在 strict 模式下,這個選項不會起任何作用。預設值為 false
    • notify:如果設為 false,Robo 指令碼在執行開始和結束時,不會顯示螢幕通知。預設值為 true
  • postscript:在 Robo 指令碼完成後套用的執行選項:
    • terminate - 如果設為 true,Robo 測試會在 Robo 指令碼完成後停止檢索。預設值為 false

以下是在 strict 模式下執行的 Robo 指令碼範例,不會顯示螢幕通知,且會在等待三秒後停止檢索:

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

範本參數

範本參數是 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 指令碼,並賦予優先權:

  1. 具備 contextDescriptor 屬性。
  2. 具有最高的 priority (根據預設,所有 Robo 指令碼的執行 priority 1 相同)。
  3. 如果 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 會依序觸發下列事件:

  1. "Robo script 2",因為優先順序最高。
  2. "Robo script 1",因為在優先順序相同的其餘適用 Robo 指令碼中,這個指令碼出現得較早。
  3. "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 完成對受測應用程式的檢索作業後,post_crawl Robo 腳本的時間長度不得超過 15 秒,否則系統可能會因逾時而終止檢索。
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 相同,提供的功能也類似。

觸發後,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 忽略特定 UI 小工具,或特定畫面上的所有 UI 小工具。這些指令會以忽略「動作」的形式表示,分別對應 eventType ELEMENT_IGNOREDALL_ELEMENTS_IGNORED

如果含有忽略動作的 Robo 指令碼的 contextDescriptor 屬性與特定畫面相符,Robo 就不會與忽略動作鎖定的任何 UI 小工具互動 (除非其他 Robo 指令碼動作讓 Robo 對其中一個忽略的 UI 小工具執行動作)。

Robo 指令碼可包含忽略、條件式和非條件式動作。與其他 Robo 指令碼動作不同,只要包含忽略動作的 Robo 指令碼的 contextDescriptor 在 Robo 檢索期間與畫面相符,系統就會套用忽略動作,無論 prioritymaxNumberOfRuns 屬性的值為何。

以下是含有兩個 Robo 腳本的檔案範例。第一個 Robo 指令碼會讓 Robo 忽略含有資源 ID "my.app.package:id/ignored_screen" 的 UI 小工具所在畫面上的所有 UI 小工具。第二個 Robo 指令碼會讓 Robo 忽略資源 ID 符合 Java 規則運算式 ".*:id/done" 的 UI 小工具,這些小工具位於含有資源 ID 為 "my.app.package:id/main_screen" 的 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 指令碼會以 recyclerViewChildPosition 形式,擷取 RecyclerView 子項目的絕對資料位置,這些子項目是 Robo 指令碼動作的目標。Robo 指令碼也會擷取 AdapterView 子項的絕對資料位置,做為 Robo 指令碼動作的目標,如 adapterViewChildPosition 所示。

系統會依下列步驟對 RecyclerView 和 AdapterView 子項執行動作:

  1. Robo 測試會透過包含 RecyclerView 或 AdapterView 的定位動作,確保對應子項顯示在畫面上。

  2. 由於子項元素已顯示在畫面上,因此 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 指令碼,並在 Test Lab 中執行

您可以在 Android Studio 中建立 Robo 指令碼,並將指令碼儲存為 JSON 檔案。然後,您可以將 JSON 檔案上傳至 Firebase Test Lab ,並視需要執行測試。

執行附有指令碼的 Robo 測試時,Robo 測試會先逐步執行您預先寫好的動作,再照常檢索應用程式。

如要在 Android Studio 中建立 Robo 指令碼 JSON 檔案,請按照「使用 Android Studio 中的 Test Lab 錄製 Robo 指令碼」一文中的步驟操作。

Robo 指令碼動作

下列常見的選用屬性適用於所有動作:

  • description - 協助在 Robo 測試輸出內容中追蹤這項 Robo 指令碼動作的執行情況。

斷言

如果所斷言的條件為 true,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 互斥。
matchIndex 使用 visionText 識別目標元素時,指定相符目標元素的出現次數索引。如果是 0,Robo 指令碼動作會選取第一個相符的元素;如果是 1,Robo 指令碼動作會選取第二個相符的元素,依此類推。排序方式為從左到右、從上到下。預設值為 0 (系統會挑選第一個相符項目)。
maxNumberOfRuns 指定要點選軟體鍵盤隨機元素的次數 (eventTypeSOFT_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 在畫面上偵測到的第二個「"Search"」字詞:

{
  "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 shell 指令

下表列出必要屬性:

屬性 說明
"eventType": "ADB_SHELL_COMMAND" --
command 要執行的 Android Debug Bridge (ADB) 殼層指令。

選用屬性包括:

  • 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 互斥。
matchIndex 使用 visionText 識別目標元素時,指定相符目標元素的出現次數索引。如果是 0,Robo 指令碼動作會選取第一個相符的元素;如果是 1,Robo 指令碼動作會選取第二個相符的元素,依此類推。排序方式為從左到右、從上到下。預設值為 0 (系統會挑選第一個相符項目)。

選用屬性包括:

  • 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%)"
}

執行輸入法編輯器動作

這項動作會按下指定目標 UI 小工具的輸入法編輯器 (IME) 上的目前動作按鈕,例如「下一步」、「完成」和「搜尋」。

下表列出必要屬性:

屬性 說明
"eventType": "PRESSED_EDITOR_ACTION" --
elementDescriptors 使用 Android UI 層級識別目標 UI 小工具。

以下是 Robo 指令碼動作的範例,可對資源 ID 為 "com.google.samples.apps.topeka:id/first_name" 的 UI 小工具執行輸入法編輯器動作:

{
  "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" --

以下是按下主畫面按鈕的 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 指定滑動方向:
  • Left
  • Right
  • Up
  • Down
  • Forward - 視目標 UI 小工具的垂直或水平捲動性而定,為 DownRight
  • Backward - 視目標 UI 小工具的垂直或水平捲動性而定,可以是 UpLeft
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 座標。與 pointTapXPercentpointTapYPercent 互斥。
pointTapYCoordinate 觸碰點的像素 Y 座標。與 pointTapXPercentpointTapYPercent 互斥。
pointTapXPercent 觸碰點的 X 座標百分比。與 pointTapXCoordinatepointTapYCoordinate 互斥。
pointTapYPercent 輕觸點的 Y 座標百分比。與 pointTapXCoordinatepointTapYCoordinate 互斥。

以下是 Robo 指令碼動作範例,可輕觸畫面中央:

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

輕觸元素內的某個點

下表列出必要屬性:

屬性 說明
"eventType": "POINT_TAP_ELEMENT" --
pointTapXPercent 目標元素內的 X 座標百分比。
pointTapYPercent 目標元素內的百分比 Y 座標。
elementDescriptors 使用 Android UI 層級結構識別目標 UI 小工具。

以下是 Robo 指令碼動作範例,可將 SeekBar 的滑桿向右移動:

{
  "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 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"
    }
  ]
}

後續步驟