Mappatura di prova

Questa è una breve introduzione di Test Mapping e una spiegazione di come iniziare a configurare facilmente i test in Android Open Source Project (AOSP).

Che cos'è la mappatura dei test?

Test Mapping è un approccio basato su Gerrit che consente agli sviluppatori di creare regole di test prima e dopo l'invio direttamente nell'albero dei sorgenti di Android e lasciare che le decisioni di rami e dispositivi vengano testate all'infrastruttura di test stessa. Le definizioni di Test Mapping sono file JSON denominati TEST_MAPPING che possono essere inseriti in qualsiasi directory di origine.

Atest può utilizzare i file TEST_MAPPING per eseguire i test di preinvio nelle directory associate. Con Test Mapping, puoi aggiungere lo stesso set di test per inviare i controlli in anticipo con una semplice modifica all'interno dell'albero dei sorgenti di Android.

Guarda questi esempi:

Aggiungi i test di preinvio a TEST_MAPPING per services.core

Aggiungi i test di preinvio a TEST_MAPPING per strumenti/dexter utilizzando le importazioni

Test Mapping si basa sul Test Harness della Trade Federation (TF) per l'esecuzione dei test e la segnalazione dei risultati.

Definizione dei gruppi di prova

Test Mapping raggruppa i test tramite un gruppo di test . Il nome di un gruppo di test può essere qualsiasi stringa. Ad esempio, il preinvio può riguardare l'esecuzione di un gruppo di test durante la convalida delle modifiche. E i test post-invio possono essere utilizzati per convalidare le build dopo che le modifiche sono state unite.

Regole dello script di creazione del packaging

Affinché la Trade Federation Test Harness possa eseguire i moduli di test di Test Mapping per una data build, questi moduli devono avere test_suite impostato per Soong o LOCAL_COMPATIBILITY_SUITE impostato per Make su una di queste due suite:

  • general-tests : test che non dipendono dalla funzionalità specifica del dispositivo (come l'hardware specifico del fornitore che la maggior parte dei dispositivi non dispone). La maggior parte dei test dovrebbe essere nella suite di test generali, anche se sono specifici per un ABI o bit o funzionalità hardware come HWASan (c'è una destinazione test_suites separata per ogni ABI) e anche se devono essere eseguiti su un dispositivo.
  • device-tests : test che dipendono dalla funzionalità specifica del dispositivo. In genere questi test si trovano in vendor/ . Poiché "specifico del dispositivo" non si riferisce alle funzionalità ABI o SoC che altri dispositivi potrebbero o meno avere, ma solo a funzionalità uniche per un dispositivo, questo vale per i test JUnit tanto quanto i test nativi di GTest (che di solito dovrebbero essere general-tests anche se specifici per ABI).

Esempi:

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

Configurazione dei test per l'esecuzione in una suite di test

Per eseguire un test all'interno di una suite di test, il test:

  • non deve avere alcun provider di build.
  • deve ripulire al termine, ad esempio, eliminando eventuali file temporanei generati durante il test.
  • modificare le impostazioni di sistema al valore predefinito o originale.
  • non dovrebbe assumere un dispositivo in un certo stato, ad esempio, root ready. La maggior parte dei test non richiede il privilegio di root per l'esecuzione. Se un test deve richiedere root, dovrebbe specificarlo con un RootTargetPreparer nel suo AndroidTest.xml , come nell'esempio seguente:
<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>

Creazione di file di mappatura dei test

Per la directory che richiede la copertura del test, aggiungi semplicemente un file JSON TEST_MAPPING simile all'esempio seguente. Queste regole assicureranno che i test vengano eseguiti nei controlli di preinvio quando vengono toccati file in quella directory o in una delle sue sottodirectory.

Seguendo un esempio

Ecco un esempio di file TEST_MAPPING (è in formato JSON ma con commenti supportati):

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

Impostazione degli attributi

Nell'esempio precedente, presubmit e postsubmit sono i nomi di ciascun gruppo di test . Vedere Definizione dei gruppi di test per ulteriori informazioni sui gruppi di test.

Il nome del modulo di test o il nome del test di integrazione della Trade Federation (percorso della risorsa al file XML di test, ad es. uiautomator/uiautomator-demo ) può essere impostato nel valore dell'attributo name . Si noti che il campo del nome non può utilizzare il name della classe o il name del metodo di test. Per restringere i test da eseguire, puoi utilizzare opzioni come include-filter qui. Vedere ( utilizzo del campione include-filtro ).

L'impostazione dell'host di un test indica se il test è un test senza dispositivo in esecuzione sull'host o meno. Il valore predefinito è false , il che significa che il test richiede l'esecuzione di un dispositivo. I tipi di test supportati sono HostGTest per i binari GTest e HostTest per i test JUnit.

L'attributo file_patterns consente di impostare un elenco di stringhe regex per la corrispondenza del percorso relativo di qualsiasi file di codice sorgente (relativo alla directory contenente il file TEST_MAPPING). Nell'esempio precedente, test CtsWindowManagerDeviceTestCases verrà eseguito in preinvio solo quando qualsiasi file java inizia con Window o Activity, che esiste nella stessa directory del file TEST_MAPPING o in una qualsiasi delle sue sottodirectory, viene modificato. È necessario eseguire l'escape delle barre inverse \ poiché si trovano in un file JSON.

L'attributo imports consente di includere i test in altri file TEST_MAPPING senza copiare il contenuto. Si noti che verranno inclusi anche i file TEST_MAPPING nelle directory padre del percorso importato. Test Mapping consente importazioni nidificate; questo significa che due file TEST_MAPPING possono importarsi a vicenda e Test Mapping è in grado di unire correttamente i test inclusi.

L'attributo options contiene ulteriori opzioni della riga di comando di TradeFed.

Per ottenere un elenco completo delle opzioni disponibili per un determinato test, eseguire:

tradefed.sh run commandAndExit [test_module] --help

Fare riferimento a TradeFed Option Handling per maggiori dettagli su come funzionano le opzioni.

Esecuzione di test con Atest

Per eseguire le regole del test di preinvio in locale:

  1. Vai alla directory contenente il file TEST_MAPPING.
  2. Esegui il comando:
atest

Vengono eseguiti tutti i test di preinvio configurati nei file TEST_MAPPING della directory corrente e delle relative directory padre. Atest individuerà ed eseguirà due test per il preinvio (A e B).

Questo è il modo più semplice per eseguire i test di preinvio nei file TEST_MAPPING nella directory di lavoro corrente (CWD) e nelle directory principali. Atest individuerà e utilizzerà il file TEST_MAPPING in CWD e in tutte le sue directory principali.

Codice sorgente strutturato

L'esempio seguente mostra come è possibile configurare i file TEST_MAPPING nell'albero di origine.

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

Contenuto di src/TEST_MAPPING :

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

Contenuto di src/project_1/TEST_MAPPING :

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

Contenuto di src/project_2/TEST_MAPPING :

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

Specificare le directory di destinazione

È possibile specificare una directory di destinazione per eseguire i test nei file TEST_MAPPING in quella directory. Il comando seguente eseguirà due test (A, B).

atest --test-mapping src/project_1

Esecuzione delle regole del test post-invio

Puoi anche usare questo comando per eseguire le regole di test postsubmit definite in TEST_MAPPING in src_path (predefinito su CWD) e le sue directory principali:

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

Esecuzione solo di test che non richiedono alcun dispositivo

È possibile utilizzare l'opzione --host per Atest per eseguire solo i test configurati sull'host che non richiedono alcun dispositivo. Senza questa opzione, Atest eseguirà entrambi i test, quelli che richiedono un dispositivo e quelli in esecuzione sull'host e non richiedono alcun dispositivo. I test verranno eseguiti in due suite separate.

atest [--test-mapping] --host

Identificazione dei gruppi di test

È possibile specificare i gruppi di test nel comando Atest. Il comando seguente eseguirà tutti i test post-invio relativi ai file nella directory src/project_1, che contiene solo un test (C).

Oppure puoi usare :all per eseguire tutti i test indipendentemente dal gruppo. Il comando seguente esegue quattro test (A, B, C, X):

atest --test-mapping src/project_1:all

Comprese le sottodirectory

Per impostazione predefinita, l'esecuzione dei test in TEST_MAPPING con Atest eseguirà solo i test di preinvio configurati nel file TEST_MAPPING in CWD (o nella directory specificata) e nelle relative directory principali. Se vuoi eseguire i test in tutti i file TEST_MAPPING nelle sottodirectory, usa l'opzione --include-subdir per forzare Atest a includere anche quei test.

atest --include-subdir

Senza l'opzione --include-subdir , Atest eseguirà solo il test A. Con l'opzione --include-subdir , Atest eseguirà due test (A, B).

Il commento a livello di riga è supportato

Puoi aggiungere un commento // -format a livello di riga per arricchire il file TEST_MAPPING con una descrizione dell'impostazione che segue. ATest and Trade Federation pre-elabora il TEST_MAPPING in un formato JSON valido senza commenti. Per mantenere il file JSON pulito e di facile lettura, è supportato solo il commento // -format a livello di riga.

Esempio:

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