Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

マルチデバイス テスト

VTS では、複数の Android デバイス間での通信を必要とするテストが可能です。

アーキテクチャ

VTS は、TradeFed フレームワークを使用してデバイス シリアルを取得し、テスト モジュールに渡します。

図 1: デバイス シリアルを渡す VTS

デバイス数やデバイスタイプなどのデバイス要件は、テストプランの設定で指定します。たとえば、Sailfish ビルド ターゲットを持つ 2 台の Android デバイスが必要なテストプランを指定できます。

デバイスの割り当て

テスト インフラストラクチャ(通常はテスト スケジューラ)は、テストプラン設定で指定された要件を満たす使用可能なデバイスを VTS フレームワークに割り当てます。割り当てられたデバイスは、テスト モジュールが使用していない場合でもテストプラン用に予約されます。VTS エージェントのバイナリは、実行しないように明確に指定されていない限り、すべての割り当てられたデバイスに転送されて実行されます。これにより、シェル スクリプトと HAL RPC の TCP 接続がテスト スクリプト内ですべてのデバイスから使用可能になります。

テスト作成ツール

フレームワークは、シリアル番号を受信したすべてのデバイスでテスト作成ツールを実行します。ターゲット作成ツールは、単一デバイスとマルチデバイスのどちらでも構いません。

  • 単一デバイス ターゲット作成ツール(VtsDeviceInfoCollector の例):
    • 必須デバイスリストがあるテストプラン設定でのみ指定できます。今後のバージョンでモジュール レベルの設定が可能になります。
    • デバイス シリアルを 1 つだけ受け取ります。
    • 特定のデバイスに対して準備タスクとクリーンアップ タスクを実行します。
  • マルチデバイス ターゲット作成ツール(VtsPythonVirtualenvPreparer の例):
    • テストプラン設定またはテスト モジュール設定で指定します。
    • すべてのデバイス シリアル番号を受け取ります。
    • 各デバイスまたはすべてのデバイスに対して準備タスクとクリーンアップ タスクを実行します。

テスト モジュール

テスト モジュールは、テスト作成ツールがホストやデバイスのセットアップを完了してから、デバイスのリストを取得します。ホスト側の Python テスト モジュールは、マルチデバイス テスト モジュールごとに 1 つずつ実行されます。割り当てられた Android デバイスは、Python テスト モジュールから AndroidDevice オブジェクトのリストとしてアクセスできます。

    devices = self.android_devices
    device1 = devices[0]
    device1_serial = device1.serial
    

プラン内のテスト モジュールが 1 台のデバイスしか使用していなくても、割り当てられたすべてのデバイスがテストプラン用に予約されます。

テスト中のデバイスの通信

有効なマルチ Android テストでは、割り当てられたデバイス間の通信が必要です。そのようなテストを開発する際は、割り当てられたデバイス間の通信方法を決定する必要があります。次のセクションでは、通信の例を 3 つ示します。なお、テスト デベロッパーが他のモデルを設計するのは自由です。

タイプ 1: ホスト側の HAL テスト

ホスト側の HAL テストでは、デフォルトでデバイスに転送される VTS HAL ドライバを使用できます。

図 2: ホスト側の HAL テスト

次のようになります。

  • テストロジックはホストで実行されます。
  • ホスト側のテスト スクリプトが、各デバイスのドライバへの RPC 呼び出しを発行します。
  • ホスト側がデバイス間のやり取りを調整します。

タイプ 2: ホスト側のエージェント ベースのテスト

ホスト側のテストでは、デバイス上で VTS エージェントを使用する代わりに、各デバイスに独自のエージェント(アプリやバイナリ)を転送することもできます。

図 3: ホスト側、エージェント ベースのテスト

次のようになります。

  • テストロジックはホストで実行されます。
  • エージェント アプリ(またはバイナリ)を各デバイスにインストールします。
  • ホスト側のテスト スクリプトが各デバイスのアプリにコマンドを発行します。
  • ホスト側がデバイス間のやり取りを調整します。

たとえば、現在の VTS リポジトリにある Next Billion User のテストは、ホスト側、アプリベース、マルチデバイスのテストです。

タイプ 3: ターゲット側の HIDL テスト

ターゲット側のマルチデバイス HIDL テストでは、すべてのテストロジックをデバイス側のテストバイナリに持たせます。このため、テスト実行中にデバイスを同期させる必要があります。

図 4: ターゲット ベースの HIDL テスト

次のようになります。

  • テストロジックはデバイス上で実行されます。
  • ホスト側のフレームワークが初期デバイス ID を提供します。
  • ターゲット側のテストバイナリの同期が必要です。
    • すべてのデバイスで同じテストバイナリ。
    • 役割ごとに異なるテストバイナリ。

例: マルチデバイス テストプラン

次の例では、2 台のデバイスの設定を指定します。

  • デバイス 1 には、ビルド プロバイダと VtsDeviceInfoCollector ターゲット作成ツールが含まれています。
  • デバイス 2 には、これらに加えて、ホスト駆動に関連したファイルのグループを転送する FilePusher 作成ツールが含まれています。
    <configuration description="VTS Codelab Plan">
      ...
    <device name="device1">
    <build_provider class="com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider" />
    <target_preparer class="com.android.tradefed.targetprep.VtsDeviceInfoCollector" />
    </device>
    <device name="device2" >
    <build_provider class="com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider" />
    <target_preparer class="com.android.tradefed.targetprep.VtsDeviceInfoCollector" />
    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
    <option name="push-group" value="HostDrivenTest.push" />
    </target_preparer>
    </device>
    <option name="compatibility:include-filter" value="VtsCodelabHelloWorldMultiDeviceTest" />
    </configuration>
    

例: ホスト側の Python テスト スクリプト

テスト作成ツールの詳細と例については、テスト作成ツールをご覧ください。ホスト側のマルチデバイスの完全な例については、hello_world_multi codelab をご覧ください。

    def setUpClass(self):
    logging.info('number of device: %s', self.android_devices)
    asserts.assertEqual(len(self.android_devices), 2, 'number of device is wrong.')
    self.dut1 = self.android_devices[0]
    self.dut2 = self.android_devices[1]
    self.shell1 = self.dut1.shell
    self.shell2 = self.dut2.shell

    def testSerialNotEqual(self):
    '''Checks serial number from two device not being equal.'''
    command = 'getprop | grep ro.serial'
    res1 = self.shell1.Execute(command)
    res2 = self.shell2.Execute(command)

    def getSerialFromShellOutput(output):
    '''Get serial from getprop query'''
    return output[const.STDOUT][0].strip().split(' ')[-1][1:-1]
    serial1 = getSerialFromShellOutput(res1)
    serial2 = getSerialFromShellOutput(res2)

    logging.info('Serial number of device 1 shell output: %s', serial1)
    logging.info('Serial number of device 2 shell output: %s', serial2)
    asserts.assertNotEqual(serial1, serial2, 'serials from two devices should not be the same')
    asserts.assertEqual(serial1, self.dut1.serial, 'serial got from device system property is different from allocated serial')
    asserts.assertEqual(serial2, self.dut2.serial, 'serial got from device system property is different from allocated serial')