測試對應

本文簡要介紹測試對應,並說明如何在 Android 開放原始碼計畫 (AOSP) 中開始設定測試。

關於測試對應

測試對應是以 Gerrit 為基礎的方法,可讓開發人員直接在 Android 來源樹狀結構中建立預先提交和提交後測試規則,並將要測試的分支和裝置的決策交給測試基礎架構。測試對應定義是名為 TEST_MAPPING 的 JSON 檔案,您可以將其放在任何來源目錄中。

Atest 可以使用 TEST_MAPPING 檔案,在相關聯的目錄中執行預先提交測試。透過測試對應,您可以在 Android 來源樹中進行最少的變更,即可將同一組測試新增至預先提交檢查。

請參閱以下範例:

測試對應項會依據 Trade Federation (TF) 測試架構執行測試並回報結果。

定義測試群組

使用測試群組測試對應群組。測試群組名稱可以是任何字串。舉例來說,presubmit 可以是驗證變更時要執行的一組測試名稱。而 postsubmit 則是在變更合併後,用來驗證建構版本的測試。

套件建構指令碼規則

如要讓 Trade Federation 測試架構為特定建構版本執行測試模組,這些模組必須為 Soong 設定 test_suites,或為 Make 設定 LOCAL_COMPATIBILITY_SUITE,並將其設為下列其中一個套件:

  • general-tests 適用於不依賴裝置特定功能 (例如大多數裝置沒有的供應商專屬硬體) 的測試。即使測試專屬於某個 ABI、位元數或硬體功能 (例如 HWASan,每個 ABI 都有個別的 test_suites 目標),甚至必須在裝置上執行,大多數測試都應位於 general-tests 套件中。
  • device-tests 適用於依附裝置特定功能的測試。這些測試通常位於 vendor/ 下方。裝置專屬是指裝置獨有的功能,因此適用於 JUnit 測試和 GTest 測試 (即使是 ABI 專屬測試,通常也應標示為 general-tests)。

例如:

Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests

設定要在測試套件中執行的測試

如要在測試套件中執行測試,測試必須符合下列條件:

  • 不得有任何建構供應商。
  • 完成後必須清理,例如刪除測試期間產生的任何暫時檔案。
  • 必須將系統設定變更為預設值或原始值。
  • 不應假設裝置處於特定狀態,例如根目錄已就緒。 大多數測試不需要根層級權限即可執行。如果測試必須具備根存取權,則應在 AndroidTest.xml 中使用 RootTargetPreparer 指定,如下例所示:

    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
    

建立測試對應檔

如要為需要測試涵蓋範圍的目錄新增 TEST_MAPPING JSON 檔案,請參閱範例。這些規則可確保在該目錄或任何子目錄中觸及任何檔案時,測試會在預先提交檢查中執行。

查看範例

以下是 TEST_MAPPING 檔案範例 (採用 JSON 格式,但支援註解):

{
  "presubmit": [
    // JUnit test with options and file patterns.
    {
      "name": "CtsWindowManagerDeviceTestCases",
      "options": [
        {
          "include-annotation": "android.platform.test.annotations.RequiresDevice"
        }
      ],
      "file_patterns": ["(/|^)Window[^/]*\\.java", "(/|^)Activity[^/]*\\.java"]
    },
    // Device-side GTest with options.
    {
      "name" : "hello_world_test",
      "options": [
        {
          "native-test-flag": "\"servicename1 servicename2\""
        },
        {
          "native-test-timeout": "6000"
        }
      ]
    }
    // Host-side GTest.
    {
      "name" : "net_test_avrcp",
      "host" : true
    }
  ],
  "postsubmit": [
    {
      "name": "CtsDeqpTestCases",
      "options": [
        {
          // Use regex in include-filter which is supported in AndroidJUnitTest
          "include-filter": "dEQP-EGL.functional.color_clears.*"
        }
      ]
    }
  ],
  "imports": [
    {
      "path": "frameworks/base/services/core/java/com/android/server/am"
    }
  ]
}

設定屬性

範例中,presubmitpostsubmit 是每個測試群組的名稱。如要進一步瞭解測試群組,請參閱「定義測試群組」。

您可以在 name 屬性的值中,設定測試模組名稱或 Trade Federation 整合測試名稱 (測試 XML 檔案的資源路徑,例如 uiautomator/uiautomator-demo)。請注意,name 欄位無法使用 name 類別或測試方法 name。如要縮小要執行的測試範圍,請使用 include-filter 等選項。請參閱include-filter 範例用法

測試的 host 設定會指出測試是否為在主機上執行的無裝置測試。預設值為 false,表示測試需要裝置才能執行。支援的測試類型包括 GTest 二進位檔的 HostGTest,以及 JUnit 測試的 HostTest

file_patterns 屬性可讓您設定規則運算式字串清單,用來比對任何原始碼檔案的相對路徑 (相對於包含 TEST_MAPPING 檔案的目錄)。在範例中,只有當 Java 檔案以 WindowActivity 開頭,且位於與 TEST_MAPPING 檔案相同的目錄或任何子目錄中時,測試 CtsWindowManagerDeviceTestCases 才會在預先提交時執行。反斜線 (\) 必須逸出,因為它們位於 JSON 檔案中。

imports 屬性可讓您在其他 TEST_MAPPING 檔案中加入測試,不必複製內容。匯入路徑上層目錄中的 TEST_MAPPING 檔案也會一併匯入。測試對應允許巢狀匯入,也就是說,兩個 TEST_MAPPING 檔案可以互相匯入,而測試對應可以合併納入的測試。

options 屬性包含其他 Tradefed 指令列選項。

如要查看特定測試的完整可用選項清單,請執行:

tradefed.sh run commandAndExit [test_module] --help

如要進一步瞭解選項的運作方式,請參閱「Tradefed 中的選項處理方式」。

使用 Atest 執行測試

如要在本機執行預先提交測試規則,請執行下列指令:

  1. 前往包含 TEST_MAPPING 檔案的目錄。
  2. 執行下列指令:

    atest
    

系統會執行目前目錄及其上層目錄 TEST_MAPPING 檔案中設定的所有預先提交測試。Atest 會找出並執行兩項預先提交測試 (A 和 B)。

這是最簡單的方法,可在目前工作目錄 (CWD) 和上層目錄的 TEST_MAPPING 檔案中執行預先提交測試。Atest 會在 CWD 和所有上層目錄中尋找並使用 TEST_MAPPING 檔案。

原始碼結構

以下範例說明如何在來源樹狀結構中設定 TEST_MAPPING 檔案:

src
├── project_1
│   └── TEST_MAPPING
├── project_2
│   └── TEST_MAPPING
└── TEST_MAPPING

src/TEST_MAPPING的內容:

{
  "presubmit": [
    {
      "name": "A"
    }
  ]
}

src/project_1/TEST_MAPPING的內容:

{
  "presubmit": [
    {
      "name": "B"
    }
  ],
  "postsubmit": [
    {
      "name": "C"
    }
  ],
  "other_group": [
    {
      "name": "X"
    }
  ]}

src/project_2/TEST_MAPPING的內容:

{
  "presubmit": [
    {
      "name": "D"
    }
  ],
  "import": [
    {
      "path": "src/project_1"
    }
  ]}

指定目標目錄

您可以指定目標目錄,在該目錄的 TEST_MAPPING 檔案中執行測試。下列指令會執行兩項測試 (A、B):

atest --test-mapping src/project_1

執行提交後測試規則

您也可以使用這個指令,在 src_path (預設為 CWD) 和其父項目錄中,執行 TEST_MAPPING 中定義的提交後測試規則:

atest [--test-mapping] [src_path]:postsubmit

只執行不需要裝置的測試

您可以使用 Atest 的 --host 選項,只執行針對主機設定的測試,這些測試不需要裝置。如果沒有這個選項,Atest 會同時執行需要裝置的測試,以及在不需要裝置的主機上執行的測試。測試會在兩個不同的套件中執行:

atest [--test-mapping] --host

找出測試群組

您可以在 Atest 指令中指定測試群組。下列指令會執行 src/project_1 目錄中與檔案相關的所有 postsubmit 測試,該目錄只包含一項測試 (C)。

或者,您可以使用 :all 執行所有測試,不論群組為何。下列指令會執行四項測試 (A、B、C、X):

atest --test-mapping src/project_1:all

包含子目錄

根據預設,使用 Atest 在 TEST_MAPPING 中執行測試時,只會執行 CWD (或指定目錄) 及其上層目錄中 TEST_MAPPING 檔案內設定的預先提交測試。如要在子目錄的所有 TEST_MAPPING 檔案中執行測試,請使用 --include-subdir 選項,強制 Atest 也納入這些測試。

atest --include-subdir

如果沒有 --include-subdir 選項,Atest 只會執行測試 A。使用 --include-subdir 選項時,Atest 會執行兩項測試 (A、B)。

支援行層級註解

您可以新增行層級的 // 格式註解,在 TEST_MAPPING 檔案中加入後續設定的說明。ATest 和 Trade Federation preprocess TEST_MAPPING 為有效的 JSON 格式,且不含註解。為確保 JSON 檔案乾淨整潔,系統僅支援行層級的 // 格式註解。

例子:

{
  // For presubmit test group.
  "presubmit": [
    {
      // Run test on module A.
      "name": "A"
    }
  ]
}