Módulos para vários dispositivos

Este documento oferece instruções detalhadas sobre como criar módulos para vários dispositivos e destaca as limitações atuais quando conhecidas.

A amostra

Um módulo multidispositivo CTS com reconhecimento de Wi-Fi é fornecido. Ele envia uma mensagem de um dispositivo por Wi-Fi e verifica se o outro dispositivo a recebe.

A origem do módulo está em packages/modules/Wifi/tests/hostsidetests/multidevices/test/aware/.

Anotação do exemplo com comentários que achamos úteis.

Etapa 1: criar a pasta do módulo

É recomendável criar uma pasta para o módulo de vários dispositivos no projeto do pacote a que ele pertence. Por exemplo: cts/hostsidetests/multidevices/. Recomendamos isso para que todos os módulos multidispositivos permaneçam posicionados pelo menos no início, o que facilitará a descoberta de exemplos.

Todos os arquivos desse módulo precisam ser colocados na própria pasta de módulo. Por exemplo: wifi_aware.

Etapa 2: criar o teste

É aqui que você implementa sua lógica de teste. Ela depende muito do que está sendo testado.

Crie a origem do teste do Mobly, como: wifi_aware_test.py.

Etapa 3: criar o arquivo de build: Android.bp

Adicione um arquivo Android.bp como packages/modules/Wifi/tests/hostsidetests/multidevices/test/Android.bp. Defina um módulo python_test_host, semelhante a:

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

Especifique os snippets para o teste com o campo de dados, que será empacotado com o binário e pode ser localizado e instalado no teste pelo ATest ou em execução contínua.

Os pacotes de snippets do Mobly estão disponíveis no Android em external/mobly-bundled-snippets/.

Opcional: criar snippets personalizados

Alguns módulos para vários dispositivos podem exigir snippets personalizados do Mobly. O teste de exemplo inclui um snippet compatível com Wi-Fi em packages/modules/Wifi/tests/hostsidetests/multidevices/com.google.snippet.wifi/aware/WifiAwareSnippet.java, criado com o Mobly Snippet Lib, disponível no Android em: external/mobly-snippet-lib/.

O snippet precisa ser definido com a regra android_test no Android.bp como instrumentação padrão:

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

Etapa 4: criar o módulo config: AndroidTest.xml

Adicione um arquivo AndroidTest.xml como packages/modules/Wifi/tests/hostsidetests/multidevices/test/aware/AndroidTest.xml. Nesta configuração de teste, você precisa especificar dois dispositivos para o teste, semelhante a:

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

Observe que:

  • Este teste de amostra depende do Mobly. Qualquer dependência pode ser especificada para PythonVirtualenvPreparer e será instalada com pip.
  • O mobly-par-file-name para MoblyBinaryHostTest precisa corresponder ao nome do módulo, como no Android.bp.
  • Especifique um mobly-test-timeout para o teste. Ele está em milissegundos e se aplica à execução binária completa do Python (todos os casos de teste juntos). Isso é necessário para evitar que os casos de teste fiquem para sempre em caso de alguns problemas.
  • Cada tag device pode conter uma configuração distinta em cada dispositivo. A configuração do Mobly as recebe na mesma ordem especificada no XML.

Relacionado à instalação do apk do snippet:

  • O POC inicial foi atualizado para instalar snippets de APKs pelo target_preparer devido à conversa com a equipe de cobertura: para garantir que as medições de cobertura não sejam excluídas muito cedo, a desinstalação pelo Harness em vez do código de teste em binários do Python oferece melhores garantias em termos de tempo.

Etapa 5: executar o teste localmente: atest

No momento, os testes em vários dispositivos só são executados em dispositivos físicos. Antes de executar o teste, verifique se os dispositivos de teste estão no estado adequado. O comando adb devices vai informar a lista dos seus dispositivos conectados. Se a lista contiver dispositivos não destinados a testes, especifique os dispositivos para o teste usando a flag -s.

Para testes de Wi-Fi, verifique se o Wi-Fi está ativado nos dispositivos após a redefinição para a configuração original.

É possível executar o teste localmente com atest:

$ atest CtsWifiAwareTestCases

O número de dispositivos usados vai aparecer no cabeçalho do resumo na saída do teste, algo como Test executed with 2 device(s).

Solução de problemas

Se o teste falhar durante a execução local devido a:

Erro do virtualenv

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

Verifique se virtualenv está no seu PATH. Adicione "~/.local/bin" ao PATH para corrigir o problema. Se o virtualenv não estiver instalado, siga estas etapas: https://virtualenv.pypa.io/en/latest/installation.html

Esperava-se pelo menos dois objetos de controlador, mas só houve um.

Os módulos de teste são de vários dispositivos ou de um único dispositivo, não há módulos mistos. Se você tentar executar um módulo de vários dispositivos sem vários dispositivos, este erro será exibido:

Expected to get at least 2 controller objects, got 1

Executar o módulo no modo de vários dispositivos resolve o problema.

Para o CTS: é possível usar a fragmentação para acioná-la (por exemplo: --shard-count 2) ou run cts-multidevces.