テスト テンプレート

AOSP には、VTS ランナーの BaseTest のホスト側の Python サブクラスとは別のテスト モジュール用のテスト テンプレートが含まれています。

図 1. テスト テンプレートのアーキテクチャ

このテンプレートを使用すると、テストの統合作業を最小限に抑えることができます。このセクションでは、テスト テンプレート(VTS の testcases/template ディレクトリにあります)の設定と使用方法、よく使用するテンプレートの例を示します。

BinaryTest テンプレート

BinaryTest テンプレートを使用して、VTS のターゲット デバイスで実行するテストを統合します。ターゲット側のテストには、次のものがあります。

  • コンパイルされてデバイスに push された C++ ベースのテスト
  • バイナリにコンパイルされたターゲット側の Python テスト
  • デバイスで実行可能なシェル スクリプト

以上のテストは、BinaryTest テンプレートの有無にかかわらず VTS に統合できます。

ターゲット側のテストと BinaryTest テンプレートの統合

BinaryTest テンプレートは、ターゲット側のテストを簡単に統合できるように設計されています。ほとんどの場合、AndroidTest.xml に簡単な設定を数行加えるだけです。以下は、VtsDeviceTreeEarlyMountTest から抜粋した設定の例です。

<configuration description="Config for VTS VtsDeviceTreeEarlyMountTest.">
  ...
<test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
<option name="test-module-name" value="VtsDeviceTreeEarlyMountTest"/>
<option name="binary-test-source" value="_32bit::DATA/nativetest/dt_early_mount_test/dt_early_mount_test" />
<option name="binary-test-source" value="_64bit::DATA/nativetest64/dt_early_mount_test/dt_early_mount_test" />
<option name="test-timeout" value="5m"/>
</test>
</configuration>

この設定は以下のようなものです。

  • binary-test-sourcebinary-test-type はテンプレート固有です。
  • テストバイナリ ソースの相対ホストパスを指定すると、テンプレートで、準備、ファイルのプッシュ、テストの実行、結果の解析、クリーンアップができるようになります。
  • テンプレートには、サブクラスがオーバーライドする、テストケースの作成関連のメソッドが含まれます。
  • テンプレートはテストバイナリ モジュールごとに 1 つのテストケースを想定しており、デフォルトでバイナリ ソースファイル名がテストケース名として使用されます。

設定オプション

BinaryTest テンプレートには、次の設定オプションがあります。

オプション名 値の型 説明
binary-test-source 文字列 バイナリテストのソースパス(ホスト上の vts test-case ディレクトリから)。
例: DATA/nativetest/test
binary-test-working-directory 文字列 作業ディレクトリ(デバイス側のパス)。
例: /data/local/tmp/testing/
binary-test-envp 文字列 バイナリ用の環境変数。
例: PATH=/new:$PATH
binary-test-args 文字列 テストの引数またはフラグ。
例: --gtest_filter=test1
binary-test-ld-library-path 文字列 LD_LIBRARY_PATH 環境変数。
例: /data/local/tmp/lib
binary-test-disable-framework ブール値 テスト前に adb stop を実行して、Android フレームワークを無効にします。 例: true
binary-test-stop-native-servers ブール値 テスト中に適切に設定されたすべてのネイティブ サーバーを停止します。例: true
binary-test-type 文字列 テンプレート タイプ。他のテンプレート タイプはこのテンプレートの拡張となりますが、binary-test-source をすでに指定しているため、このテンプレートにこのオプションを指定する必要はありません。

値の型が strings のオプションについては、設定でそのオプションを繰り返すことで、複数の値を追加できます。たとえば、VtsDeviceTreeEarlyMountTest の例のように binary-test-source を 2 回設定します。

テストタグ

テストタグを追加するには、strings 値のオプションの前に、:: を区切りに使用して追加します。テストタグは、名前は同じで、ビット数や親ディレクトリが異なるバイナリソースを含める場合に特に便利です。たとえば、名前が同じでソース ディレクトリが異なるソースのファイル プッシュや結果の名前の衝突を避けるには、これらのソースに異なるタグを指定します。

2 つの dt_early_mount_test ソースがある VtsDeviceTreeEarlyMountTest の例では、テストタグは binary-test-source_32bit:: プレフィックスと _64bit:: プレフィックスです。32bit または 64bit で終わるタグは、テストをどちらかの ABI ビット数で利用可能だと自動的にマークします。つまり、タグ _32bit の付いたテストは、64 ビット ABI では実行されません。タグを指定しなかった場合は、空の文字列のタグを使用した場合と同じになります。

同じタグを持つオプションはグループ化され、他のタグから分離されます。たとえば、_32bit タグが付いた binary-test-args は、同じタグが付いた binary-test-source にのみ適用され、同じタグが付いた binary-test-working-directory で実行されます。バイナリテストでは binary-test-working-directory オプションは省略可能で、タグに 1 つの作業ディレクトリを指定できます。たとえば、binary-test-working-directory オプションが指定されていない場合、デフォルトのディレクトリが各タグに使用されます。

タグ名は、結果レポートのテストケース名に直接追加されます。 たとえば、タグ _32bit が付いたテストケース testcase1 は、結果レポートでは testcase1_32bit と表示されます。

BinaryTest テンプレートを使用しないターゲット側のテストの統合

VTS では、VTS ランナーの BaseTest から拡張されたホスト側の Python テストがデフォルトのテスト形式です。ターゲット側のテストを統合するには、まずテストファイルをデバイスにプッシュし、シェルコマンドを使用してテストを実行してから、ホスト側の Python スクリプトを使用して結果を解析します。

テストバイナリのプッシュ

ファイルのプッシュには、VtsFilePusher ターゲット作成ツールの使用をおすすめします。例:

<target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
        <option name="push" value="DATA/test->/data/local/tmp/test"/>
    </target_preparer>

VtsFilePusher では、次の処理が行われます。

  1. デバイスの接続を確認する。
  2. ソースファイルの絶対パスを特定する。
  3. adb push コマンドを使用してファイルをプッシュする。
  4. テスト完了後にファイルを削除する。

あるいは、同じような処理を行うホスト側の Python テスト スクリプトを使用して、手動でファイルをプッシュすることもできます。

テストの実行

ファイルをデバイスにプッシュした後、ホスト側の Python テスト スクリプトの中でシェルコマンドを使用してテストを実行します。例:

device = self.android_devices[0]
res = device.shell.Execute(["chmod a+x /data/local/tmp/test", "/data/local/tmp/test"])
asserts.AssertFalse(any(res[return_codes]))

GtestBinaryTest テンプレート

GtestBinaryTest テンプレートは、GTest テストバイナリをホストし、それぞれには通常複数のテストケースが含まれます。このテンプレートは、セットアップ、テストケースの作成、結果解析のメソッドをオーバーライドして BinaryTest を拡張するため、BinaryTest の設定がすべて継承されます。

GtestBinaryTest では、以下のようにオプション gtest-batch-mode が追加されています。

オプション名 値の型 説明
binary-test-type 文字列 テンプレート タイプ。値 gtest を使用します。
gtest-batch-mode ブール値 Gtest バイナリをバッチモードで実行します。例: true

一般に、gtest-batch-modetrue に設定するとパフォーマンスが向上しますが、信頼性はわずかに低下します。VTS 準拠テストでは、多くのモジュールがパフォーマンス向上のためにバッチモードを使用しています。ただし、信頼性を確保するため、モードが指定されていない場合は、デフォルトで非バッチモードになります。

非バッチモード

非バッチモードでは、テストケースごとに GTest バイナリを個別に呼び出します。たとえば、GTest バイナリに 10 個のテストケースがある場合(ホスト側の設定でフィルタした後)、バイナリはデバイスシェル上で毎回異なるテストフィルタで 10 回呼び出されます。テストケースごとに別々の GTest 結果出力が XML として生成され、テンプレートによって解析されます。

図 2. 非バッチモード

非バッチモードを使用するメリットには、次のようなものがあります。

  • テストケースの分離。あるテストケースがクラッシュやハングをしても、他のテストケースには影響を与えません。
  • 詳細レベル。テストケースごとのプロファイリングやカバレッジの測定結果、systrace、bugreport、logcat などを簡単に取得できます。テスト結果とログは、各テストケースの終了後すぐに取得されます。

非バッチモードを使用するデメリットには、次のようなものがあります。

  • 読み込みの重複。GTest バイナリが呼び出されるたびに、関連するライブラリが読み込まれ、クラスの初期セットアップが実行されます。
  • 通信のオーバーヘッド。テストが 1 つ完了すると、ホストデバイスとターゲット デバイスの間で、結果の解析と次のコマンドのための通信が発生します(今後最適化される可能性もあります)。

バッチモード

GTest バッチモードでは、ホスト側の設定でフィルタされたすべてのテストケースを含む長いテストフィルタ値で、テストバイナリが 1 回だけ呼び出されます(これにより、非バッチモードで読み込みに重複が生じる問題が回避できます)。GTest のテスト結果は、output.xml またはターミナル出力を使用して解析できます。

output.xml を使用する場合(デフォルト)は、次のようになります。

図 3. バッチモード、output.xml

非バッチモードの場合と同様に、GTest 出力 XML ファイルを使用してテスト結果が解析されます。ただし、すべてのテストが完了した後に出力 XML ファイルが生成されるため、テストケースでバイナリまたはデバイスがクラッシュした場合、結果の XML ファイルは生成されません。

ターミナル出力を使用する場合は、次のようになります。

図 4. バッチモード、ターミナル出力

GTest の実行中は、テストログと進行状況を、フレームワークがテストのステータス、結果、ログを解析できる形式でターミナルに出力します。

バッチモードを使用するメリットには、次のようなものがあります。

  • テストケースの分離。クラッシュした後にフレームワークがテストフィルタを減らして(完了したテストケースとクラッシュしたテストケースを除外して)バイナリやデバイスを再起動した場合、非バッチモードと同じレベルでテストケースを分離します。
  • 詳細レベル。詳細レベルは非バッチモードと同じです。

バッチモードを使用するデメリットには、次のようなものがあります。

  • 管理コスト。GTest ログ形式が変更されると、すべてのテストが正しく動作しなくなります。
  • 混乱。テストケースで GTest の進行状況に類似した形式のものが出力され、これによって形式に混乱が生じる可能性があります。

このようなデメリットがあるため、コマンドライン出力を使用するためのオプションを一時的に削除しました。この機能の信頼性を高めるため、今後このオプションを再検討します。

HostBinaryTest テンプレート

HostBinaryTest テンプレートには、他のディレクトリや Python スクリプトに存在しないホスト側の実行ファイルが含まれています。このテストで以下の情報がわかります。

  • ホストで実行可能なコンパイル済みテストバイナリ
  • シェルや Python などの言語で記述された実行可能なスクリプト

1 つの例として、以下の VTS セキュリティ SELinux ポリシーのホスト側テストがあります。

<configuration description="Config for VTS  Security SELinux policy host-side test cases">
    ...
    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
        <option name="test-module-name" value="VtsSecuritySelinuxPolicyHost"/>
        <option name="binary-test-source" value="out/host/linux-x86/bin/VtsSecuritySelinuxPolicyHostTest" />
        <option name="binary-test-type" value="host_binary_test"/>
    </test>
</configuration>

HostBinaryTest は BinaryTest テンプレートの拡張ではありませんが、同じようなテスト設定を使用します。上記の例では、binary-test-source オプションは、テスト実行ファイルへのホスト側の相対パスを指定し、binary-test-typehost_binary_test です。BinaryTest テンプレートと同様、バイナリ ファイル名はデフォルトでテストケース名として使用されます。

既存のテンプレートの拡張

テンプレートをテスト設定で直接使用して Python 以外のテストを含めたり、テンプレートを拡張して特定のテスト要件を扱うサブクラスを作成したりできます。VTS リポジトリのテンプレートには、次の拡張があります。

図 5. VTS リポジトリ内の既存のテンプレートを拡張する

すべてのテスト要件で、既存のテンプレートを拡張することをおすすめします。テンプレートを拡張する一般的な理由は、次のとおりです。

  • 特殊な手順でテストをセットアップするため(特殊なコマンドでデバイスの準備をするなど)。
  • さまざまなテストケースとテスト名を生成するため。
  • コマンド出力を読み取って、あるいは他の条件を使用して、結果を解析するため。

既存のテンプレートを拡張しやすくするため、テンプレートには各機能に特化したメソッドが含まれています。既存のテンプレートの設計を改良した場合は、VTS のコードベースに貢献することをおすすめします。