Módulos multidispositivo

En este documento, se proporcionan instrucciones paso a paso para crear módulos multidispositivo y se indican las limitaciones actuales cuando se conocen.

La muestra

Se proporciona un módulo multidispositivo compatible con Wi-Fi del CTS. Envía un mensaje desde un dispositivo a través de Wi-Fi y verifica que el otro dispositivo lo reciba.

El código fuente del módulo se encuentra en packages/modules/Wifi/tests/hostsidetests/multidevices/test/aware/.

Anotamos el ejemplo con tantos comentarios como consideramos útiles.

Paso 1: Crea la carpeta del módulo

Se recomienda crear una carpeta para tu módulo de varios dispositivos en el proyecto de la suite al que pertenece. Por ejemplo, cts/hostsidetests/multidevices/. Recomendamos esto para que todos los módulos multidispositivo permanezcan ubicados en el mismo lugar, al menos al principio, lo que facilitará el descubrimiento de ejemplos.

Todos los archivos de este módulo deben colocarse en su propia carpeta de módulo. Por ejemplo: wifi_aware.

Paso 2: Crea la prueba

Aquí es donde implementas la lógica de tu prueba. Depende mucho de lo que se esté probando.

Crea la fuente de prueba de Mobly, como wifi_aware_test.py.

Paso 3: Crea el archivo de compilación: Android.bp

Agrega un archivo Android.bp como packages/modules/Wifi/tests/hostsidetests/multidevices/test/Android.bp. Define un módulo python_test_host, similar al siguiente:

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",
    ],
}

Especifica los fragmentos para la prueba con el campo de datos, que se empaquetará con el archivo binario y ATest o la ejecución continua podrán ubicarlo e instalarlo en la prueba.

Los fragmentos agrupados de Mobly están disponibles en Android en external/mobly-bundled-snippets/.

Opcional: Crea fragmentos personalizados

Es posible que algunos módulos multidispositivo requieran fragmentos de Mobly personalizados. La prueba de ejemplo incluye un fragmento de código compatible con Wi-Fi Aware en packages/modules/Wifi/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippet.java, que se compila con Mobly Snippet Lib, disponible en Android en external/mobly-snippet-lib/.

El fragmento debe definirse con la regla android_test en Android.bp como la instrumentación estándar:

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",
    ],
}

Paso 4: Crea la configuración del módulo: AndroidTest.xml

Agrega un archivo AndroidTest.xml como packages/modules/Wifi/tests/hostsidetests/multidevices/test/aware/AndroidTest.xml. En esta configuración de prueba, debes especificar dos dispositivos para la prueba, de manera similar a lo siguiente:

<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>

Ten en cuenta lo siguiente:

  • Esta prueba de ejemplo tiene una dependencia en Mobly. Se puede especificar cualquier dependencia para PythonVirtualenvPreparer, y se instalará con pip.
  • El mobly-par-file-namede MoblyBinaryHostTest debe coincidir con el nombre del módulo como en Android.bp.
  • Especifica un mobly-test-timeout para la prueba. Se expresa en milisegundos y se aplica a la ejecución completa del objeto binario de Python (todos los casos de prueba juntos). Esto es necesario para evitar que los casos de prueba se queden colgados para siempre en caso de que haya algún problema.
  • Cada etiqueta device puede contener una configuración distinta en cada dispositivo. La configuración de Mobly las recibirá en el mismo orden en que se especificaron en el XML.

Relacionado con la instalación de APK de fragmentos:

  • Se actualizó la prueba de concepto inicial para instalar APKs de fragmentos a través de target_preparer debido a una conversación con el equipo de Cobertura: Para garantizar que las mediciones de cobertura no se borren demasiado pronto, la desinstalación por parte de Harness en lugar de por código de prueba en los archivos binarios de Python ofrece mejores garantías en términos de sincronización.

Paso 5: Ejecuta la prueba de forma local: atest

Actualmente, las pruebas multidispositivo solo se ejecutan en dispositivos físicos. Antes de ejecutar la prueba, verifica que los dispositivos de prueba estén en el estado adecuado. El comando adb devices debería mostrar la lista de tus dispositivos conectados. Si la lista contiene dispositivos que no están destinados a las pruebas, especifica los dispositivos para la prueba con la marca -s.

En el caso de las pruebas de Wi-Fi, asegúrate de que la conexión Wi-Fi esté habilitada en los dispositivos (después de restablecer la configuración de fábrica).

Puedes ejecutar la prueba de forma local con atest:

$ atest CtsWifiAwareTestCases

Deberías ver la cantidad de dispositivos que se usaron en el encabezado del resumen del resultado de atest, algo como Test executed with 2 device(s).

Solución de problemas

Si la prueba falla cuando se ejecuta de forma local debido a lo siguiente:

Error de virtualenv

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

Asegúrate de que virtualenv esté en tu PATH. Agregar "~/.local/bin" a PATH debería solucionar el problema. Si virtualenv no está instalado, sigue las instrucciones en https://virtualenv.pypa.io/en/latest/installation.html.

Se esperaba recibir al menos 2 objetos de controlador, pero se recibió 1

Los módulos de prueba son de varios dispositivos o de un solo dispositivo. No hay módulos mixtos. Si intentas ejecutar un módulo de varios dispositivos sin tener varios dispositivos, verás este error:

Expected to get at least 2 controller objects, got 1

Ejecutar el módulo en el modo de varios dispositivos solucionará el problema.

En el caso del CTS, puedes usar la fragmentación para activarlo (por ejemplo, --shard-count 2) o run cts-multidevces.