マルチデバイス モジュール

このドキュメントでは、マルチデバイス モジュールを作成する方法について詳しく説明します。現在、既知の制限事項がある場合にはあわせて紹介します。

サンプル

CTS の Wi-Fi 対応マルチデバイス モジュールが提供されています。このモジュールは、一方のデバイスから Wi-Fi 経由でメッセージを送信し、もう一方のデバイスがメッセージを受信したことを確認します。

このモジュールのソースは packages/modules/Wifi/tests/hostsidetests/multidevices/test/aware/ にあります。

例にはアノテーションを付け、有用と思われるコメントを可能な限り加えました。

ステップ 1: モジュール フォルダを作成する

マルチデバイス モジュールが属するスイート プロジェクトには、モジュール用のフォルダを作成することをおすすめします(例: cts/hostsidetests/multidevices/)。これは、すべてのマルチデバイス モジュールが最初だけでも 1 つの場所に配置されていると、例を見つけやすくなるためです。

マルチデバイス モジュールのファイルはすべて、それぞれ個別のモジュール フォルダに配置する必要があります(例: wifi_aware)。

ステップ 2: テストを作成する

ここで、テストロジックを実装します。テストロジックは、テストの内容によって大きく異なります。

Mobly のテストソースを作成します(例: wifi_aware_test.py)。

ステップ 3: ビルドファイルを作成する: Android.bp

packages/modules/Wifi/tests/hostsidetests/multidevices/test/Android.bp のような Android.bp ファイルを追加します。次のような python_test_host モジュールを定義します。

python_test_host {
    name: "CtsWifiAwareTestCases",
    main: "wifi_aware_test.py",
    srcs: ["wifi_aware_test.py"],
    test_suites: [
        "cts",
        "general-tests",
    ],
    test_options: {
        unit_test: false,
    },
    data: [
          // Package the snippet with the mobly test
        ":wifi_aware_snippet",
    ],
}

データ フィールドにテストのスニペットを指定すると、このスニペットはバイナリデータにパックされ、ATest によるテストや連続実行の際に検索、インストールできるようになります。

Mobly Bundled Snippet は、Android の external/mobly-bundled-snippets/ で入手できます。

必要な場合のみ: カスタム スニペットを作成する

一部のマルチデバイス モジュールでは、カスタムの Mobly スニペットが必要になる場合があります。サンプルテストには、packages/modules/Wifi/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippet.java にある Wi-Fi 対応のスニペットが含まれています。これは、Android の external/mobly-snippet-lib/ で入手できる Mobly Snippet Lib でビルドされています。

スニペットは、標準のインストルメンテーションと同様に、Android.bp の android_test ルールで定義する必要があります。

android_test {
    name: "wifi_aware_snippet",
    sdk_version: "current",
    srcs: [
        "CallbackUtils.java",
        "WifiAwareSnippet.java",
    ],
    manifest: "AndroidManifest.xml",
    static_libs: [
        "androidx.test.runner",
        "guava",
        "mobly-snippet-lib",
    ],
}

ステップ 4: モジュール構成を作成する: AndroidTest.xml

packages/modules/Wifi/tests/hostsidetests/multidevices/test/aware/AndroidTest.xml のような AndroidTest.xml ファイルを追加します。このテスト構成では、次のように、2 つのデバイスをテスト用に指定する必要があります。

<configuration description="Config for CTS Wifi Aware test cases">
    <option name="test-suite-tag" value="cts" />
    <option name="config-descriptor:metadata" key="component" value="wifi" />
    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
    <option name="config-descriptor:metadata" key="parameter" value="not_secondary_user" />

    <device name="device1">
        <!-- For coverage to work, the APK should not be uninstalled until after coverage is pulled.
             So it's a lot easier to install APKs outside the python code.
        -->
        <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
            <option name="test-file-name" value="wifi_aware_snippet.apk" />
        </target_preparer>
        <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
            <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
            <option name="run-command" value="wm dismiss-keyguard" />
        </target_preparer>
        <target_preparer class="com.android.tradefed.targetprep.PythonVirtualenvPreparer">
          <!-- Any python dependencies can be specified and will be installed with pip -->
          <option name="dep-module" value="mobly" />
        </target_preparer>
    </device>
    <device name="device2">
        <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
            <option name="test-file-name" value="wifi_aware_snippet.apk" />
        </target_preparer>
        <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
            <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
            <option name="run-command" value="wm dismiss-keyguard" />
        </target_preparer>
    </device>

    <test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest">
      <!-- The mobly-par-file-name should match the module name -->
      <option name="mobly-par-file-name" value="CtsWifiAwareTestCases" />
      <!-- Timeout limit in milliseconds for all test cases of the python binary -->
      <option name="mobly-test-timeout" value="60000" />
    </test>
</configuration>

次のことに注意してください。

  • このサンプルテストには Mobly との依存関係が存在します。PythonVirtualenvPreparer には任意の依存関係を指定でき、pip とともにインストールされます。
  • MoblyBinaryHostTestmobly-par-file-name は、Android.bp で使用されているモジュール名と一致する必要があります。
  • テストの mobly-test-timeout を指定してください。これはミリ秒単位であり、完全な Python バイナリ実行に適用されます(すべてのテストケースを合わせて)。これは、いくつかの問題が発生した場合にテストケースが永久にハングするのを回避するために必要です。
  • device タグには、デバイスごとに異なる設定を含めることができます。Mobly 構成は、XML 内で指定されているのと同じ順序でそれらの設定を受け取ります。

スニペット APK のインストールの関連情報:

  • カバレッジ チームと交換した情報に基づき、target_preparer を介してスニペット APK をインストールするよう最初の POC が更新されました。Python バイナリのテストコードではなく Harness によってアンインストールすることにより、タイミングに関する確実性を改善し、カバレッジの測定値の削除までに十分な期間が確保されるようにしました。

ステップ 5: ローカルでテストを実行する: atest

現在、マルチデバイス テストは物理デバイスでのみ実行されます。テストを実行する前に、テストデバイスが適切な状態にあることを確認してください。コマンド adb devices を実行すると、接続済みのデバイスのリストが出力されます。リストにテスト用ではないデバイスが含まれている場合は、-s フラグを使用してテスト用のデバイスを指定します。

Wi-Fi テストの場合は、デバイスで Wi-Fi が有効になっていることを確認してください(出荷時の設定にリセットした後)。

atest を使用してテストをローカルで実行できます。

$ atest CtsWifiAwareTestCases

概要の見出しで使用されるデバイスの数が表示されます。atest の出力は Test executed with 2 device(s) のようになります。

トラブルシューティング

ローカルで実行したテストが失敗し、次のようなエラーが返された場合:

virtualenv エラー

java.io.IOException: Cannot run program
"virtualenv": error=2, No such file or directory

virtualenv が PATH に含まれていることを確認してください。「~/.local/bin」を PATH に追加すると、問題が修正されます。 virtualenv がインストールされていない場合は、https://virtualenv.pypa.io/en/latest/installation.html を参照してください。

コントローラ オブジェクトが 2 つ以上取得されるはずですが、実際には 1 つだけでした

テスト モジュールはマルチデバイスかシングル デバイスのいずれかであり、混合モジュールは存在しません。複数のデバイスを指定せずにマルチデバイス モジュールを実行しようとすると、次のようなエラーが発生します。

Expected to get at least 2 controller objects, got 1

モジュールをマルチデバイス モードで実行することで、問題を解決できます。

CTS の場合: シャーディングを使用してトリガーするか(例: --shard-count 2)、または run cts-multidevces を使用できます。