mapeamento de teste

Esta é uma breve introdução ao mapeamento de testes e uma explicação de como começar a configurar testes facilmente no Android Open Source Project (AOSP).

Sobre mapeamento de teste

O mapeamento de teste é uma abordagem baseada em Gerrit que permite aos desenvolvedores criar regras de teste pré e pós-envio diretamente na árvore de origem do Android e deixar as decisões de ramificações e dispositivos a serem testados para a própria infraestrutura de teste. As definições de mapeamento de teste são arquivos JSON denominados TEST_MAPPING que podem ser colocados em qualquer diretório de origem.

Atest pode usar os arquivos TEST_MAPPING para executar testes de pré-envio nos diretórios associados. Com o mapeamento de testes, você pode adicionar o mesmo conjunto de testes para pré-envio de verificações com uma simples alteração na árvore de origem do Android.

Veja estes exemplos:

Adicione testes de pré-envio a TEST_MAPPING para services.core

Adicione testes de pré-envio a TEST_MAPPING para ferramentas/dexter usando importações

O mapeamento de testes depende do Test Harness da Trade Federation (TF) para execução de testes e relatórios de resultados.

Definir grupos de teste

O mapeamento de testes agrupa testes por meio de um grupo de testes . O nome de um grupo de teste pode ser qualquer sequência. Por exemplo, o pré-envio pode ser a execução de um grupo de testes ao validar alterações. E testes pós-envio podem ser usados ​​para validar as compilações após a mesclagem das alterações.

Regras de script de construção de pacote

Para que o Trade Federation Test Harness execute os módulos de teste do mapeamento de teste para uma determinada construção, esses módulos devem ter test_suite definido para Soong ou LOCAL_COMPATIBILITY_SUITE definido para Make para um destes dois conjuntos:

  • testes gerais - testes que não dependem de funcionalidades específicas do dispositivo (como hardware específico do fornecedor que a maioria dos dispositivos não possui). A maioria dos testes deve estar no conjunto de testes gerais, mesmo que sejam específicos para uma ABI ou bitness ou recursos de hardware como HWASan (há um destino test_suites separado para cada ABI) e mesmo que tenham que ser executados em um dispositivo.
  • testes de dispositivos - testes que dependem da funcionalidade específica do dispositivo. Normalmente, esses testes serão encontrados em vendor/ . Como "específico do dispositivo" não se refere à funcionalidade ABI ou SoC que outros dispositivos podem ou não ter, mas apenas à funcionalidade exclusiva de um dispositivo, isso se aplica tanto aos testes JUnit quanto aos testes nativos do GTest (que geralmente devem ser general-tests , mesmo que sejam específicos da ABI).

Exemplos:

Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests

Configurar testes para execução em um conjunto de testes

Para que um teste seja executado dentro de um conjunto de testes, o teste:

  • não deve ter nenhum provedor de compilação.
  • deve ser limpo após a conclusão, por exemplo, excluindo quaisquer arquivos temporários gerados durante o teste.
  • altere as configurações do sistema para o valor padrão ou original.
  • não deve assumir um dispositivo em um determinado estado, por exemplo, pronto para root. A maioria dos testes não requer privilégio de root para ser executada. Se um teste precisar exigir root, ele deverá especificar isso com um RootTargetPreparer em seu AndroidTest.xml , como no exemplo a seguir:
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>

Crie arquivos de mapeamento de teste

Para o diretório que requer cobertura de teste, basta adicionar um arquivo JSON TEST_MAPPING semelhante ao exemplo abaixo. Essas regras garantirão que os testes sejam executados em verificações de pré-envio quando qualquer arquivo for tocado nesse diretório ou em qualquer um de seus subdiretórios.

Siga um exemplo

Aqui está um exemplo de arquivo TEST_MAPPING (está no formato JSON, mas com suporte para comentários):

{
  "presubmit": [
    // JUnit test with options and file patterns.
    {
      "name": "CtsWindowManagerDeviceTestCases",
      "options": [
        {
          "include-annotation": "android.platform.test.annotations.RequiresDevice"
        }
      ],
      "file_patterns": ["(/|^)Window[^/]*\\.java", "(/|^)Activity[^/]*\\.java"]
    },
    // Device-side GTest with options.
    {
      "name" : "hello_world_test",
      "options": [
        {
          "native-test-flag": "\"servicename1 servicename2\""
        },
        {
          "native-test-timeout": "6000"
        }
      ]
    }
    // Host-side GTest.
    {
      "name" : "net_test_avrcp",
      "host" : true
    }
  ],
  "postsubmit": [
    {
      "name": "CtsWindowManagerDeviceTestCases"
    }
  ],
  "imports": [
    {
      "path": "frameworks/base/services/core/java/com/android/server/am"
    }
  ]
}

Definir atributos

No exemplo acima, presubmit e postsubmit são os nomes de cada grupo de teste . Consulte Definindo grupos de testes para obter mais informações sobre grupos de testes.

O nome do módulo de teste ou nome do teste de integração da Federação Comercial (caminho do recurso para o arquivo XML de teste, por exemplo, uiautomator/uiautomator-demo ) pode ser definido no valor do atributo name . Observe que o campo name não pode usar class name ou test method name . Para restringir os testes a serem executados, você pode usar opções como include-filter aqui. Consulte ( uso de amostra de filtro de inclusão ).

A configuração de host de um teste indica se o teste é um teste sem dispositivo em execução no host ou não. O valor padrão é false , o que significa que o teste requer a execução de um dispositivo. Os tipos de teste suportados são HostGTest para binários GTest e HostTest para testes JUnit.

O atributo file_patterns permite definir uma lista de strings regex para corresponder ao caminho relativo de qualquer arquivo de código-fonte (em relação ao diretório que contém o arquivo TEST_MAPPING). No exemplo acima, o teste CtsWindowManagerDeviceTestCases será executado no pré-envio somente quando qualquer arquivo java iniciado com Window ou Activity, que existe no mesmo diretório do arquivo TEST_MAPPING ou qualquer um de seus subdiretórios, for alterado. Barras invertidas \ precisam ser escapadas como estão em um arquivo JSON.

O atributo imports permite incluir testes em outros arquivos TEST_MAPPING sem copiar o conteúdo. Observe que os arquivos TEST_MAPPING nos diretórios pai do caminho importado também serão incluídos. O mapeamento de teste permite importações aninhadas; isso significa que dois arquivos TEST_MAPPING podem importar um ao outro e o mapeamento de teste é capaz de mesclar adequadamente os testes incluídos.

O atributo options contém opções adicionais de linha de comando do TradeFed.

Para obter uma lista completa de opções disponíveis para um determinado teste, execute:

tradefed.sh run commandAndExit [test_module] --help

Consulte Tratamento de opções TradeFed para obter mais detalhes sobre como as opções funcionam.

Execute testes com Atest

Para executar as regras de teste de pré-envio localmente:

  1. Vá para o diretório que contém o arquivo TEST_MAPPING.
  2. Execute o comando:
atest

Todos os testes de pré-envio configurados nos arquivos TEST_MAPPING do diretório atual e de seus diretórios pai são executados. Atest localizará e executará dois testes para pré-envio (A e B).

Esta é a maneira mais simples de executar testes de pré-envio em arquivos TEST_MAPPING no diretório de trabalho atual (CWD) e nos diretórios pai. Atest localizará e usará o arquivo TEST_MAPPING no CWD e em todos os seus diretórios pai.

Estruturar código-fonte

O exemplo a seguir mostra como os arquivos TEST_MAPPING podem ser configurados na árvore de origem.

src
├── project_1
│   └── TEST_MAPPING
├── project_2
│   └── TEST_MAPPING
└── TEST_MAPPING

Conteúdo de src/TEST_MAPPING :

{
  "presubmit": [
    {
      "name": "A"
    }
  ]
}

Conteúdo de src/project_1/TEST_MAPPING :

{
  "presubmit": [
    {
      "name": "B"
    }
  ],
  "postsubmit": [
    {
      "name": "C"
    }
  ],
  "other_group": [
    {
      "name": "X"
    }
  ]}

Conteúdo de src/project_2/TEST_MAPPING :

{
  "presubmit": [
    {
      "name": "D"
    }
  ],
  "import": [
    {
      "path": "src/project_1"
    }
  ]}

Especifique os diretórios de destino

Você pode especificar um diretório de destino para executar testes em arquivos TEST_MAPPING nesse diretório. O comando a seguir executará dois testes (A, B).

atest --test-mapping src/project_1

Execute regras de teste pós-envio

Você também pode usar este comando para executar as regras de teste pós-envio definidas em TEST_MAPPING em src_path (padrão para CWD) e seus diretórios pai:

atest [--test-mapping] [src_path]:postsubmit

Execute apenas testes que não requerem nenhum dispositivo

Você pode usar a opção --host para Atest para executar apenas testes configurados no host que não requerem nenhum dispositivo. Sem esta opção, o Atest executará ambos os testes, os que requerem dispositivo e os que são executados no host e não requerem dispositivo. Os testes serão executados em dois conjuntos separados.

atest [--test-mapping] --host

Identificar grupos de teste

Você pode especificar grupos de teste no comando Atest. O comando a seguir executará todos os testes pós-envio relacionados aos arquivos no diretório src/project_1, que contém apenas um teste (C).

Ou você pode usar :all para executar todos os testes, independentemente do grupo. O comando a seguir executa quatro testes (A, B, C, X):

atest --test-mapping src/project_1:all

Incluir subdiretórios

Por padrão, a execução de testes em TEST_MAPPING com Atest executará apenas testes de pré-envio configurados no arquivo TEST_MAPPING em CWD (ou em determinado diretório) e seus diretórios pai. Se você deseja executar testes em todos os arquivos TEST_MAPPING nos subdiretórios, use a opção --include-subdir para forçar o Atest a incluir esses testes também.

atest --include-subdir

Sem a opção --include-subdir , o Atest executará apenas o teste A. Com a opção --include-subdir , o Atest executará dois testes (A, B).

Comentários em nível de linha são suportados

Você pode adicionar um comentário // -format em nível de linha para detalhar o arquivo TEST_MAPPING com uma descrição da configuração a seguir. ATest e Trade Federation irão pré-processar o TEST_MAPPING para um formato JSON válido sem comentários. Para manter o arquivo JSON limpo e fácil de ler, apenas comentários em formato // de nível de linha são suportados.

Exemplo:

{
  // For presubmit test group.
  "presubmit": [
    {
      // Run test on module A.
      "name": "A"
    }
  ]
}