В этом документе представлены пошаговые инструкции по созданию модулей для нескольких устройств и указаны текущие ограничения, если они известны.
Пример
Предусмотрен модуль CTS с поддержкой Wi-Fi для нескольких устройств. Он отправляет сообщение с одного устройства через Wi-Fi и проверяет, получает ли его другое устройство.
Источник модуля находится по адресу cts/hostsidetests/multidevices/wifi_aware .
Мы добавили к примеру столько комментариев, сколько считаем полезными.
Шаг 1: Создайте папку модуля
Рекомендуется создать папку для вашего модуля с несколькими устройствами в проекте набора, к которому он принадлежит. Например: cts/hostsidetests/multidevices/ . Мы рекомендуем это, чтобы все модули с несколькими устройствами оставались совмещенными, по крайней мере, сначала, что облегчит поиск примеров.
 Все файлы для этого модуля должны быть помещены в отдельную папку модуля. Например: wifi_aware .
Обычно для модуля требуется файл OWNERS и в нем должен быть указан баг-компонент. См. пример в cts/hostsidetests/multidevices/wifi_aware/OWNERS .
Шаг 2. Создайте тест
Здесь вы реализуете свою тестовую логику. Это сильно зависит от того, что тестируется.
Создайте тестовый источник Mobly, например: wifi_aware_test.py .
Шаг 3: Создайте файл сборки: Android.bp
Добавьте файл Android.bp, например cts/hostsidetests/multidevices/wifi_aware/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 Snippets доступны для Android по адресу external/mobly-bundled-snippets/ .
Необязательно: создайте пользовательские фрагменты.
Для некоторых модулей с несколькими устройствами могут потребоваться пользовательские фрагменты Mobly. Пример теста включает фрагмент с поддержкой Wi-Fi по адресу cts/hostsidetests/multidevices/wifi_aware/snippet/ , созданный с помощью Mobly Snippet Lib, доступный для Android по адресу: external/mobly-snippet-lib/ .
Фрагмент должен быть определен с помощью правила android_test в Android.bp, как и стандартный инструментарий:
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
Добавьте файл AndroidTest.xml, например cts/hostsidetests/multidevices/wifi_aware/AndroidTest.xml . В этой тестовой конфигурации вам нужно указать два устройства для теста, аналогично:
<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. -  Имя 
mobly-par-file-nameдляMoblyBinaryHostTestдолжно совпадать с именем модуля, как в Android.bp. -  
mobly-test-timeoutдля теста. Он измеряется в миллисекундах и применяется к полному бинарному исполнению Python (все тестовые примеры вместе). Это необходимо, чтобы тестовые случаи не зависали навсегда в случае возникновения некоторых проблем. -  Каждый тег 
deviceможет содержать отдельные настройки на каждом устройстве. Конфигурация Mobly будет получать их в том же порядке, как указано в XML. 
Относится к установке фрагмента apk:
- Первоначальный POC был обновлен для установки фрагментов apk через target_preparer из-за разговора с командой покрытия: чтобы гарантировать, что измерения покрытия не удаляются слишком рано, удаление с помощью Harness, а не с помощью тестового кода в двоичных файлах Python обеспечивает лучшие гарантии с точки зрения времени.
 
Шаг 5: Запустите тест локально: atest
 В настоящее время тесты на нескольких устройствах выполняются только на физических устройствах. Перед запуском теста убедитесь, что ваши тестовые устройства находятся в надлежащем состоянии. Команда adb devices должна сообщить список ваших подключенных устройств. Если в списке есть устройства, не предназначенные для тестирования, укажите устройства для тестирования с помощью флага -s.
Для тестов Wi-Fi убедитесь, что Wi-Fi включен для устройств (после сброса настроек).
Вы можете запустить тест локально с помощью atest:
$ atest CtsWifiAwareTestCases
 Вы должны увидеть количество устройств, используемых в итоговом заголовке выходных данных теста, что-то вроде Test executed with 2 device(s) .
Исправление проблем
Если тест не проходит при локальном запуске из-за:
Ошибка виртуальной среды
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 .