Mappatura test

Questa è una breve introduzione al mapping dei test e una spiegazione di come iniziare a configurare i test nell'Android Open Source Project (AOSP).

Informazioni sul mapping dei test

Il mapping dei test è un approccio basato su Gerrit che consente agli sviluppatori di creare regole di test di pre-invio e post-invio direttamente nell'albero di origine Android e di lasciare all'infrastruttura di test le decisioni relative a rami e dispositivi da testare. Le definizioni di mapping dei test sono file JSON denominati TEST_MAPPING che puoi inserire in qualsiasi directory di origine.

Atest può utilizzare i file TEST_MAPPING per eseguire test di pre-invio nelle directory associate. Con il mapping dei test, puoi aggiungere lo stesso insieme di test ai controlli di pre-invio con una modifica minima all'interno dell'albero di origine Android.

Vedi questi esempi:

Il mapping dei test si basa sul framework di test Trade Federation (TF) per l' esecuzione dei test e la generazione di report sui risultati.

Definisci gruppi di test

Il mapping dei test raggruppa i test con un gruppo di test. Il nome di un gruppo di test può essere qualsiasi stringa. Ad esempio, presubmit può essere il nome di un gruppo di test da eseguire durante la convalida delle modifiche. E postsubmit può essere il nome dei test utilizzati per convalidare le build dopo l'unione delle modifiche.

Regole dello script di build del pacchetto

Affinché il framework di test Trade Federation esegua i moduli di test per una determinata build, questi moduli devono avere un test_suites impostato per Soong o un LOCAL_COMPATIBILITY_SUITE impostato per Make in una di queste due suite:

  • general-tests è per i test che non dipendono da funzionalità specifiche del dispositivo (come hardware specifico del fornitore che la maggior parte dei dispositivi non ha). La maggior parte dei test deve essere nella suite general-tests, anche se sono specifici per un ABI, una bitness o funzionalità hardware come HWASan (esiste una destinazione test_suites separata per ogni ABI) e anche se devono essere eseguiti su un dispositivo.
  • device-tests è per i test che dipendono da funzionalità specifiche del dispositivo. In genere questi test si trovano in vendor/. Specifico del dispositivo si riferisce solo alle funzionalità univoche di un dispositivo, quindi si applica sia ai test JUnit sia ai test GTest (che in genere devono essere contrassegnati come general-tests anche se sono specifici per l'ABI).

Esempi:

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

Configura i test da eseguire in una suite di test

Affinché un test venga eseguito all'interno di una suite di test:

  • Non deve avere alcun provider di build.
  • Deve eseguire la pulizia al termine, ad esempio eliminando eventuali file temporanei generati durante il test.
  • Deve modificare le impostazioni di sistema sul valore predefinito o originale.
  • Non deve presupporre che un dispositivo sia in un determinato stato, ad esempio root pronto. La maggior parte dei test non richiede privilegi di root per l'esecuzione. Se un test deve richiedere la root, deve specificarlo con RootTargetPreparer nel relativo AndroidTest.xml, come nell'esempio seguente:

    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
    

Crea file di mapping dei test

Per la directory che richiede la copertura dei test, aggiungi un file JSON TEST_MAPPING simile all'esempio. Queste regole assicurano che i test vengano eseguiti nei controlli di pre-invio quando vengono toccati file in quella directory o in una delle relative sottodirectory.

Segui un esempio

Ecco un file TEST_MAPPING di esempio (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": "CtsDeqpTestCases",
      "options": [
        {
          // Use regex in include-filter which is supported in AndroidJUnitTest
          "include-filter": "dEQP-EGL.functional.color_clears.*"
        }
      ]
    }
  ],
  "imports": [
    {
      "path": "frameworks/base/services/core/java/com/android/server/am"
    }
  ]
}

Imposta gli attributi

Nell'esempio, presubmit e postsubmit sono i nomi di ogni gruppo di test. Per ulteriori informazioni sui gruppi di test, consulta la sezione Definisci gruppi di test.

Puoi impostare il nome del modulo di test o il nome del test di integrazione di Trade Federation (percorso della risorsa al file XML di test, ad esempio, uiautomator/uiautomator-demo) nel valore dell'attributo name. Tieni presente che il campo name non può utilizzare la classe name o il metodo di test name. Per restringere i test da eseguire, utilizza opzioni come include-filter. Consulta l'utilizzo di esempio di include-filter.

L'impostazione 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 file binari GTest e HostTest per i test JUnit.

L'attributo file_patterns consente di impostare un elenco di stringhe di espressioni regolari per la corrispondenza del percorso relativo di qualsiasi file di codice sorgente (relativo alla directory contenente il file TEST_MAPPING). Nell'esempio, il test viene eseguito in pre-invio solo quando un file Java inizia con o, che esiste nella stessa directory del file o in una delle relative sottodirectory.CtsWindowManagerDeviceTestCasesWindowActivityTEST_MAPPING Le barre rovesciate (\) devono essere sottoposte a escape perché si trovano in un file JSON.

Importa file TEST_MAPPING

L'attributo imports consente di includere i test in altri file TEST_MAPPING senza copiare i contenuti. Sono inclusi anche i file TEST_MAPPING nelle directory principali del percorso importato. TEST_MAPPING consente le importazioni nidificate, il che significa che i file importati possono a loro volta importare altri file TEST_MAPPING e il mapping dei test può unire i test inclusi.

TEST_MAPPING supporta le importazioni a livello di root e a livello di gruppo:

  • Importazioni a livello di root: specificate al livello superiore del file TEST_MAPPING (al di fuori di qualsiasi gruppo di test). Un'importazione a livello di root importa l'intero file TEST_MAPPING di destinazione (e le relative directory principali) come se fosse scritto nel percorso in cui viene importato. Tutte le definizioni dei gruppi di test nel file importato (ad es. presubmit, postsubmit) vengono unite ai gruppi di test corrispondenti del file di importazione.
  • Importazioni a livello di gruppo: specificate direttamente all'interno di un gruppo di test specifico (ad esempio presubmit o postsubmit). Un'importazione a livello di gruppo è limitata rigorosamente a quel gruppo di test, il che significa che verranno importati solo i test definiti in quel gruppo specifico all'interno del file TEST_MAPPING di destinazione. Tutti gli altri gruppi di test nel file di destinazione vengono ignorati.

Le importazioni a livello di gruppo forniscono un controllo granulare sull'esecuzione dei test. Ad esempio, puoi importare test specificamente per il pre-invio senza includere test di post-invio pesanti dalla directory importata.

Esempio di importazione a livello di root:

{
  "imports": [
    {
      "path": "frameworks/base/services/core"
    }
  ],
  "presubmit": [
    {
      "name": "MyTestModule"
    }
  ]
}

Esempio di importazione a livello di gruppo:

{
  "presubmit": [
    {
      "name": "MyTestModule"
    },
    {
      "imports": [
        {
          "path": "frameworks/base/services/core"
        }
      ]
    }
  ],
  "postsubmit": [
    {
      "imports": [
        {
          "path": "frameworks/base/services/accessibility"
        }
      ]
    }
  ]
}

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

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

tradefed.sh run commandAndExit [test_module] --help

Per ulteriori dettagli su come funzionano le opzioni, consulta la sezione Gestione delle opzioni in Tradefed.

Convalide TEST_MAPPING

Quando invii modifiche che modificano i file TEST_MAPPING, vengono eseguiti controlli di pre-invio per garantire la correttezza:

  • Convalida dei pattern di file: garantisce che tutte le espressioni regolari in file_patterns corrispondano ad almeno un file nel repository. I pattern obsoleti che non corrispondono a nessun file causano l'errore del controllo.
  • Convalida in fase di build: promuove gli avvisi di convalida in fase di build raccolti dalla build per bloccare gli errori in pre-invio per i rami principali. Gli avvisi comuni includono:
    • Moduli inesistenti: riferimento a un nome di modulo di test che non esiste nel codebase, ad esempio quando il nome contiene un errore di battitura.
    • Importazioni non valide: percorsi di riferimento in imports che non esistono o non contengono un file TEST_MAPPING.
    • Problemi di schema: utilizzo di chiavi non supportate o strutture non valide nella configurazione JSON.

Esegui test con Atest

Per eseguire le regole di test di pre-invio in locale:

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

    atest
    

Vengono eseguiti tutti i test di pre-invio configurati nei file TEST_MAPPING della directory corrente e delle relative directory principali. Atest individua ed esegue due test per il pre-invio (A e B).

Questo è il modo più semplice per eseguire i test di pre-invio nei file TEST_MAPPING nella directory di lavoro corrente (CWD) e nelle directory principali. Atest individua e utilizza il file TEST_MAPPING in CWD e in tutte le relative directory principali.

Struttura del codice sorgente

Questo esempio mostra come configurare i file TEST_MAPPING nell'albero di origine:

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

Contenuti di src/TEST_MAPPING:

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

Contenuti di src/project_1/TEST_MAPPING:

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

Contenuti di src/project_2/TEST_MAPPING:

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

Specifica le directory di destinazione

Puoi specificare una directory di destinazione per eseguire i test nei file TEST_MAPPING in quella directory. Il seguente comando esegue due test (A, B):

atest --test-mapping src/project_1

Esegui le regole di test di post-invio

Puoi anche utilizzare questo comando per eseguire le regole di test di post-invio definite in TEST_MAPPING in src_path (impostazione predefinita su CWD) e nelle relative directory principali:

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

Esegui solo i test che non richiedono un dispositivo

Puoi utilizzare l'opzione --host per Atest per eseguire solo i test configurati sull'host che non richiedono un dispositivo. Senza questa opzione, Atest esegue entrambi i test, quelli che richiedono un dispositivo e quelli in esecuzione su un host che non richiede un dispositivo. I test vengono eseguiti in due suite separate:

atest [--test-mapping] --host

Identifica i gruppi di test

Puoi specificare i gruppi di test nel comando Atest. Il seguente comando esegue tutti i test postsubmit relativi ai file nella directory src/project_1, che contiene un solo test (C).

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

atest --test-mapping src/project_1:all

Includi sottodirectory

Per impostazione predefinita, l'esecuzione dei test in TEST_MAPPING con Atest esegue solo i test di pre-invio 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, utilizza l'opzione --include-subdir per forzare Atest a includere anche questi test.

atest --include-subdir

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

Commento a livello di riga supportato

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

Esempio:

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