Google is committed to advancing racial equity for Black communities. See how.
Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Esempio di test di auto-strumentazione

Quando viene avviato un test di strumentazione, il relativo pacchetto di destinazione viene riavviato con il codice di strumentazione inserito e avviato per l'esecuzione. Un'eccezione è che il pacchetto di destinazione qui non può essere il framework dell'applicazione Android stesso, ovvero il pacchetto android , perché così facendo si porterebbe alla situazione paradossale in cui il framework Android dovrebbe essere riavviato, che è ciò che supporta le funzioni di sistema, inclusa la strumentazione si.

Ciò significa che un test di strumentazione non può iniettarsi nel framework Android, ovvero il server di sistema, per l'esecuzione. Per testare il framework Android, il codice di test può richiamare solo le superfici API pubbliche o quelle esposte tramite il linguaggio di definizione dell'interfaccia Android AIDL disponibile nell'albero dei sorgenti della piattaforma. Per questa categoria di test, non è significativo indirizzare un particolare pacchetto. Pertanto, è consuetudine dichiarare tali strumentazioni come destinazione del proprio pacchetto dell'applicazione di test, come definito nel proprio tag <manifest> di AndroidManifest.xml .

A seconda dei requisiti, i pacchetti di applicazioni di test in questa categoria possono anche:

  • Attività di bundle necessarie per i test.
  • Condividi l'ID utente con il sistema.
  • Essere firmato con la chiave della piattaforma.
  • Essere compilato con l'origine del framework anziché con l'SDK pubblico.

Questa categoria di test di strumentazione viene talvolta definita auto-strumentazione. Di seguito sono riportati alcuni esempi di test di auto-strumentazione nel sorgente della piattaforma:

L'esempio qui trattato è la scrittura di un nuovo test di strumentazione con il pacchetto di destinazione impostato nel proprio pacchetto dell'applicazione di test. Questa guida utilizza il seguente test come esempio:

Si consiglia di sfogliare prima il codice per avere un'idea approssimativa prima di procedere.

Decidere una posizione di origine

In genere il tuo team avrà già uno schema stabilito di posizioni in cui archiviare il codice e luoghi in cui aggiungere test. La maggior parte dei team possiede un singolo repository git o ne condivide uno con altri team, ma ha una sottodirectory dedicata che contiene il codice sorgente del componente.

Supponendo che la posizione principale per l'origine del componente sia in <component source root> , la maggior parte dei componenti ha src e cartelle di tests sotto di essa e alcuni file aggiuntivi come Android.mk (o suddivisi in file .mk aggiuntivi), il file manifest AndroidManifest.xml e il file di configurazione di prova "AndroidTest.xml".

Dato che stai aggiungendo un nuovo test, probabilmente dovrai creare la directory dei tests accanto al tuo componente src e popolarla con il contenuto.

In alcuni casi, il tuo team potrebbe avere ulteriori strutture di directory sotto tests causa della necessità di impacchettare diverse suite di test in singoli apk. E in questo caso, dovrai creare una nuova sottodirectory sotto tests .

Indipendentemente dalla struttura, finirai per popolare la directory tests o la sottodirectory appena creata con file simili a quelli che si trovano nella directory instrumentation nella modifica gerrit di esempio. Le sezioni seguenti spiegheranno in modo più dettagliato ogni file.

File manifest

Proprio come una normale applicazione, ogni modulo di test della strumentazione necessita di un file manifest. Se assegni al file il nome AndroidManifest.xml e lo fornisci accanto ad Android.mk per il tuo modulo di prova, verrà incluso automaticamente dal makefile principale BUILD_PACKAGE .

Prima di procedere oltre, si consiglia vivamente di esaminare prima la panoramica del manifesto dell'app .

Fornisce una panoramica dei componenti di base di un file manifest e delle loro funzionalità. Guarda l'esempio su platform_testing / tests / example / instrumentation / AndroidManifest.xml .

Un'istantanea è inclusa qui per comodità:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />

    <application>
        <uses-library android:name="android.test.runner" />
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                     android:targetPackage="android.test.example.helloworld"
                     android:label="Hello World Test"/>

</manifest>

Alcuni commenti selezionati sul file manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

L'attributo del package è il nome del pacchetto dell'applicazione: questo è l'identificatore univoco che il framework dell'applicazione Android utilizza per identificare un'applicazione (o in questo contesto: l'applicazione di test). Ogni utente nel sistema può installare solo un'applicazione con quel nome di pacchetto.

Inoltre, questo attributo del package è lo stesso di quello restituito da ComponentName#getPackageName() , e anche lo stesso che ComponentName#getPackageName() per interagire con i vari comandi secondari pm tramite adb shell .

Si noti inoltre che, sebbene il nome del pacchetto sia tipicamente nello stesso stile del nome di un pacchetto Java, in realtà ha pochissime cose a che fare con esso. In altre parole, il pacchetto dell'applicazione (o di prova) può contenere classi con qualsiasi nome di pacchetto, sebbene d'altra parte si possa optare per la semplicità e avere il nome del pacchetto Java di primo livello nella propria applicazione o test identico al nome del pacchetto dell'applicazione.

android:sharedUserId="android.uid.system"

Questo dichiara che al momento dell'installazione, a questo apk dovrebbe essere concesso lo stesso ID utente, cioè l'identità di runtime, della piattaforma principale. Nota che questo dipende dal fatto che l'apk sia firmato con lo stesso certificato della piattaforma principale (vedi LOCAL_CERTIFICATE nella sezione precedente), ma sono concetti diversi:

  • alcune autorizzazioni o API sono protette dalla firma, il che richiede lo stesso certificato di firma
  • alcune autorizzazioni o API richiedono l'identità dell'utente di system del chiamante, che richiede al pacchetto chiamante di condividere l'id utente con il system , se si tratta di un pacchetto separato dalla piattaforma principale stessa
<uses-library android:name="android.test.runner" />

Ciò è richiesto per tutti i test di strumentazione poiché le classi correlate sono impacchettate in un file di libreria jar del framework separato, quindi richiede voci del percorso di classe aggiuntive quando il pacchetto di test viene richiamato dal framework dell'applicazione.

android:targetPackage="android.test.example.helloworld"

Potresti aver notato che targetPackage qui è dichiarato uguale all'attributo del package dichiarato nel tag manifest di questo file. Come accennato nelle nozioni di base sui test , questa categoria di test di strumentazione è in genere destinata al test delle API del framework, quindi non è molto significativo per loro avere un pacchetto applicativo mirato specifico, diverso da se stesso.

File di configurazione semplice

Ogni nuovo modulo di test deve avere un file di configurazione per dirigere il sistema di compilazione con i metadati del modulo, le dipendenze in fase di compilazione e le istruzioni di pacchettizzazione. Nella maggior parte dei casi, l'opzione del file Blueprint basata su Soong è sufficiente. Per i dettagli, vedere Configurazione di test semplice .

File di configurazione complesso

Per questi casi più complessi, è anche necessario scrivere un file di configurazione di prova per il cablaggio di prova di Android, Trade Federation .

La configurazione di test può specificare speciali opzioni di configurazione del dispositivo e argomenti predefiniti per fornire la classe di test. Vedi l'esempio su /platform_testing/tests/example/instrumentation/AndroidTest.xml .

Un'istantanea è inclusa qui per comodità:

<configuration description="Runs sample instrumentation test.">
  <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
  <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
    <option name="test-file-name" value="HelloWorldTests.apk"/>
  </target_preparer>
  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
  <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
  <option name="test-suite-tag" value="apct"/>
  <option name="test-tag" value="SampleInstrumentationTest"/>

  <test class="com.android.tradefed.testtype.AndroidJUnitTest">
    <option name="package" value="android.test.example.helloworld"/>
    <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
  </test>
</configuration>

Alcuni commenti selezionati sul file di configurazione del test:

<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
  <option name="test-file-name" value="HelloWorldTests.apk"/>
</target_preparer>

Questo dice a Trade Federation di installare HelloWorldTests.apk sul dispositivo di destinazione utilizzando un target_preparer specificato. Ci sono molti preparatori di destinazione disponibili per gli sviluppatori in Trade Federation e questi possono essere utilizzati per garantire che il dispositivo sia configurato correttamente prima dell'esecuzione del test.

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
  <option name="package" value="android.test.example.helloworld"/>
  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>

Specifica la classe di test di Trade Federation da utilizzare per eseguire il test e supera il pacchetto sul dispositivo da eseguire e il framework del runner di test che in questo caso è JUnit.

Per ulteriori informazioni, vedere Configurazione del modulo di test .

Caratteristiche di JUnit4

L'utilizzo della libreria android-support-test come test runner consente l'adozione di nuove classi di test in stile JUnit4 e la modifica di gerrit di esempio contiene un utilizzo molto semplice delle sue funzionalità. Guarda l'esempio su /platform_testing/tests/example/instrumentation/src/android/test/example/helloworld/HelloWorldTest.java .

Sebbene i modelli di test siano generalmente specifici per i team componenti, esistono alcuni modelli di utilizzo generalmente utili.

@RunWith(JUnit4.class)
public class HelloWorldTest {

Una differenza significativa in JUnit4 è che i test non sono più necessari per ereditare da una classe di test di base comune; invece, scrivi i test in semplici classi Java e usi l'annotazione per indicare determinate impostazioni e vincoli di prova. In questo esempio, stiamo istruendo che questa classe dovrebbe essere eseguita come un test JUnit4.

    @BeforeClass
    public static void beforeClass() {
    ...
    @AfterClass
    public static void afterClass() {
    ...
    @Before
    public void before() {
    ...
    @After
    public void after() {
    ...
    @Test
    @SmallTest
    public void testHelloWorld() {
    ...

Le annotazioni @Before e @After vengono utilizzate sui metodi di JUnit4 per eseguire la configurazione pre test e lo smontaggio post test. Allo stesso modo, le annotazioni @BeforeClass e @AfterClass vengono utilizzate sui metodi da JUnit4 per eseguire la configurazione prima di eseguire tutti i test in una classe di test e successivamente smontarli. Si noti che l'impostazione dell'ambito della classe e i metodi di smontaggio devono essere statici. Per quanto riguarda i metodi di test, a differenza della versione precedente di JUnit, non è più necessario avviare il nome del metodo con test , invece, ciascuno di essi deve essere annotato con @Test . Come al solito, i metodi di test devono essere pubblici, non dichiarare alcun valore restituito, non accettare parametri e possono generare eccezioni.

Importante : i metodi di test stessi sono annotati con @Test annotazione @Test ; e si noti che per eseguire i test tramite APCT, devono essere annotati con le dimensioni del test: il metodo annotato di esempio testHelloWorld come @SmallTest . L'annotazione può essere applicata nell'ambito del metodo o nell'ambito della classe.

Accesso alla instrumentation

Sebbene non sia trattato nell'esempio di base Hello World, è abbastanza comune che un test Android richieda l'accesso all'istanza di Instrumentation : questa è l'interfaccia API principale che fornisce l'accesso ai contesti dell'applicazione, alle API di test relative al ciclo di vita delle attività e altro ancora.

Poiché i test JUnit4 non richiedono più una classe base comune, non è più necessario ottenere l'istanza di Instrumentation tramite InstrumentationTestCase#getInstrumentation() , invece, il nuovo test runner la gestisce tramite InstrumentationRegistry dove è memorizzata l'impostazione contestuale e ambientale creata dal framework di strumentazione.

Per accedere all'istanza della classe Instrumentation , chiama semplicemente il metodo statico getInstrumentation() sulla classe InstrumentationRegistry :

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

Crea e testa a livello locale

Per i casi d'uso più comuni, utilizza Atest .

Per casi più complessi che richiedono una personalizzazione più pesante, seguire le istruzioni della strumentazione .