テスト マッピング

ここでは、テスト マッピングの概略を紹介し、Android オープンソース プロジェクト(AOSP)でテスト設定を始める方法について説明します。

テスト マッピングについて

テスト マッピングは Gerrit ベースの手法であり、デベロッパーは presubmit および postsubmit のテストルールを Android ソースツリーで直接作成し、テストするブランチとデバイスの決定をテスト インフラストラクチャに任せることができます。テスト マッピング定義は、任意のソース ディレクトリに配置できる TEST_MAPPING という JSON ファイルです。

AtestTEST_MAPPING ファイルを使用して、関連付けられたディレクトリで送信前テストを実行できます。テスト マッピングを使用すると、Android ソースツリー内で最小限の変更を行うだけで、同じテストセットを presubmit チェックに追加できます。

次の例をご覧ください。

テスト マッピングによるテスト実行と結果レポートは、Trade Federation(TF)テストハーネスを利用しています。

テストグループを定義する

テスト マッピングは、テストグループによってテストをグループ化します。テストグループの名前には任意の文字列を使用できます。たとえば、presubmit は変更の検証時に実行するテストグループの名前です。また、postsubmit は、変更を統合した後にビルドを検証するために使用されるテストです。

ビルド スクリプト ルールをパッケージ化する

Trade Federation テストハーネスで指定ビルドに対してテスト モジュールを実行するには、モジュールで、Soong の場合は test_suites を、Make の場合は LOCAL_COMPATIBILITY_SUITE を次の 2 つのテストスイートのいずれかに設定する必要があります。

  • general-tests はデバイス固有の機能に依存しないテストです(ほとんどのデバイスが備えていないベンダー固有のハードウェアなど)。ほとんどのテストは、1 種類の ABI やビットに固有のものや、ハードウェア機能(ABI ごとに異なる test_suites ターゲットがある HWASan など)に固有のものであったり、デバイスで実行する必要があったりしても、general-tests スイートに配置する必要があります。
  • device-tests はデバイス固有の機能に依存するテストです。通常、この種のテストは vendor/ の下に配置されます。デバイス固有とは、あるデバイスだけに特有の機能のことです。JUnit テストと GTest テストがこれにあてはまります(通常、ABI 固有であっても general-tests とマークされるべきです)。

例:

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

テストスイートで実行するようにテストを設定する

テストスイート内で実行するテストの要件は、次のとおりです。

  • ビルド プロバイダが指定されていない。
  • テスト中に生成された一時ファイルを削除するなどして、テスト完了後にクリーンアップしている。
  • システム設定をデフォルト値または元の値に変更している。
  • 特定の状態(ルートの準備完了など)のデバイスを想定していない。ほとんどのテストの実行に root 権限は不要です。テストで root が必要な場合は、次の例のように AndroidTest.xmlRootTargetPreparer で指定する必要があります。

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

テスト マッピング ファイルを作成する

テスト用のカバレッジを必要とするディレクトリの場合、のような TEST_MAPPING JSON ファイルを追加します。こうしたルールを使用すると、対象ディレクトリやサブディレクトリ内の任意のファイルにアクセスしたときに、presubmit チェックでテストを実行できます。

例を参照する

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 は、各テストグループの名前です。テストグループの詳細については、テストグループの定義をご覧ください。

テスト モジュールの名前や Trade Federation 統合テスト名(uiautomator/uiautomator-demo など、テスト XML ファイルへのリソースパス)は、name 属性の値で設定できます。name フィールドでは、クラス name またはテストメソッド name を使用できません。実行するテストを絞り込む場合は、include-filter などのオプションを使用します。include-filter サンプルの使用方法を参照してください。

テストの host 設定は、テストがホストで実行されるデバイスレス テストであるかどうかを示します。デフォルト値は false で、この場合はテストを実行するデバイスが必要です。サポートされているテストの種類は、GTest バイナリの場合は HostGTest、JUnit テストの場合は HostTest です。

file_patterns 属性を使用すると、ソースコード ファイルの相対パス(TEST_MAPPING ファイルを含むディレクトリの相対パス)にマッチする正規表現文字列のリストを設定できます。では、Java ファイルが Window または Activity から始まる場合のみ presubmit でテスト CtsWindowManagerDeviceTestCases を実行します。このファイルは、TEST_MAPPING ファイルと同じディレクトリかそのサブディレクトリに存在します。JSON ファイルの中では、バックスラッシュ(\)をエスケープする必要があります。

imports 属性を使用すると、コンテンツをコピーせずにテストを他の TEST_MAPPING ファイルに含めることができます。インポートされたパスの親ディレクトリにある TEST_MAPPING ファイルも含まれます。テスト マッピングでは、インポートのネストが可能です。つまり、2 つの TEST_MAPPING ファイルが互いをインポートでき、テスト マッピングに含まれるテストを統合できます。

options 属性には、追加の Tradefed コマンドライン オプションが含まれます。

特定のテストで使用可能なオプションの全リストを取得するには、次のコマンドを実行します。

tradefed.sh run commandAndExit [test_module] --help

オプションの仕組みについて詳しくは、Tradefed のオプションの処理をご覧ください。

Atest を使用してテストを実行する

presubmit テストルールをローカルで実行するには:

  1. TEST_MAPPING ファイルが含まれているディレクトリに移動します。
  2. 次のコマンドを実行します。

    atest
    

現在のディレクトリと親ディレクトリの TEST_MAPPING ファイルで設定されているすべての presubmit テストが実行されます。Atest は、presubmit の 2 つのテスト(A と B)を見つけて実行します。

これは、現在の作業ディレクトリ(CWD)と親ディレクトリにある TEST_MAPPING ファイルで presubmit テストを実行する最も簡単な方法です。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 ファイルでテストを実行できます。次のコマンドは、2 つのテスト(A、B)を実行します。

atest --test-mapping src/project_1

postsubmit テストルールを実行する

このコマンドを使用して、src_path(デフォルトは CWD)と親ディレクトリの TEST_MAPPING で定義されている postsubmit テストルールを実行することもできます。

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

デバイスを必要としないテストのみを実行する

--host オプションを使用すると、デバイスを必要としないホストに対して設定されたテストだけを Atest で実行することができます。このオプションを指定しない場合、Atest はデバイスを必要とするテスト、ホスト上で実行されデバイスを必要としないテストの両方を実行します。テストは、2 つの独立したスイートで実行されます。

atest [--test-mapping] --host

テストグループを識別する

テストグループは、Atest コマンドで指定できます。次のコマンドは、src/project_1 ディレクトリにあるファイルに関連付けられた postsubmit テストをすべて実行します。このディレクトリには、1 つのテスト(C)のみが含まれています。

または、:all を使用すると、グループに関係なくすべてのテストを実行できます。次のコマンドは、4 つのテスト(A、B、C、X)を実行します。

atest --test-mapping src/project_1:all

サブディレクトリを含める

デフォルトでは、Atest を使用して TEST_MAPPING 内のテストを実行すると、CWD(または指定ディレクトリ)と親ディレクトリの TEST_MAPPING ファイルで構成された presubmit テストのみが実行されます。サブディレクトリ内のすべての TEST_MAPPING ファイルでテストを実行するには、--include-subdir オプションを使用して Atest に強制的にこれらのテストを追加します。

atest --include-subdir

--include-subdir オプションを指定しない場合、Atest はテスト A のみを実行します。--include-subdir オプションを指定すると、Atest は 2 つのテスト(A、B)を実行します。

行レベルのコメントのサポート

行レベルの // 形式のコメントを追加して、以下のように TEST_MAPPING ファイルに設定の説明を追加できます。ATest と Trade Federation は TEST_MAPPING を前処理して、コメントがない有効な JSON 形式にします。JSON ファイルの明瞭さを保持するため、行レベルの // 形式のコメントのみがサポートされています。

例:

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