ここでは、テスト マッピングの概略を紹介し、Android オープンソース プロジェクト(AOSP)でテスト設定を始める方法について説明します。
テスト マッピングについて
テスト マッピングは Gerrit ベースの手法であり、デベロッパーは presubmit および postsubmit のテストルールを Android ソースツリーで直接作成し、テストするブランチとデバイスの決定をテスト インフラストラクチャに任せることができます。テスト マッピング定義は、任意のソース ディレクトリに配置できる TEST_MAPPING
という JSON ファイルです。
Atest は TEST_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.xml
のRootTargetPreparer
で指定する必要があります。<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"
}
]
}
属性を設定する
例の presubmit
と postsubmit
は、各テストグループの名前です。テストグループの詳細については、テストグループの定義をご覧ください。
テスト モジュールの名前や 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 テストルールをローカルで実行するには:
TEST_MAPPING
ファイルが含まれているディレクトリに移動します。次のコマンドを実行します。
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"
}
]
}