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.
Ecco alcuni esempi:
Aggiungere test di pre-invio a
TEST_MAPPINGperservices.coreAggiungere test di pre-invio a
TEST_MAPPINGpertools/dexterutilizzando le importazioni
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.
Definire i 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 (ad esempio hardware specifico del fornitore che la maggior parte dei dispositivi non ha). La maggior parte dei test deve essere nella suitegeneral-tests, anche se sono specifici per un ABI o una bitness o funzionalità hardware come HWASan (esiste un targettest_suitesseparato 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 invendor/. 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 comegeneral-testsanche se sono specifici per ABI).
Esempi:
Android.bp: test_suites: ["general-tests"],
Android.mk: LOCAL_COMPATIBILITY_SUITE := general-tests
Configurare 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
RootTargetPreparernel relativoAndroidTest.xml, come nell'esempio seguente:<target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
Creare 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.
Seguire 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 Definire i 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'esempio di utilizzo
include-filter campione.
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.
L'attributo imports consente di includere i test in altri file TEST_MAPPING senza copiare i contenuti. Vengono inclusi anche i file TEST_MAPPING nelle directory principali del percorso importato. Il mapping dei test consente le importazioni nidificate. Ciò significa che due file TEST_MAPPING possono importarsi a vicenda e il mapping dei test può unire i test inclusi.
L'attributo options contiene ulteriori opzioni della riga di comando di Tradefed.
Per visualizzare un elenco completo delle opzioni disponibili per un determinato test, esegui:
tradefed.sh run commandAndExit [test_module] --help
Per ulteriori dettagli sul funzionamento delle opzioni, consulta la sezione Gestione delle opzioni in Tradefed.
Eseguire i test con Atest
Per eseguire localmente le regole di test di pre-invio:
- Vai alla directory contenente il file
TEST_MAPPING. 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.
Strutturare il 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"
}
]}
Specificare 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
Eseguire 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
Eseguire 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
Identificare 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
Includere le 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"
}
]
}