Targeting di un esempio di applicazione

Questa categoria di test della strumentazione non è molto diversa da quelle destinate alle normali applicazioni Android. Vale la pena notare che l'applicazione di test che includeva la strumentazione deve essere firmata con lo stesso certificato dell'applicazione a cui è destinata.

Tieni presente che questa guida presuppone che tu abbia già una certa conoscenza del flusso di lavoro dell'albero di origine della piattaforma. In caso contrario, fare riferimento a Requisiti . L'esempio trattato qui è la scrittura di un nuovo test della strumentazione con il pacchetto di destinazione impostato nel proprio pacchetto dell'applicazione di test. Se non hai familiarità con il concetto, leggi l' introduzione al test della piattaforma .

Questa guida utilizza il seguente test come esempio:

  • framework/base/pacchetti/Shell/test

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

Decidere una posizione di origine

Poiché il test della strumentazione sarà destinato a un'applicazione, la convenzione prevede di inserire il codice sorgente del test in una directory tests sotto la radice della directory di origine del componente nell'albero dei sorgenti della piattaforma.

Vedi altre discussioni sulla posizione della sorgente nell'esempio end-to-end per i test autostrumentali .

File manifesto

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 tmodule di prova, verrà incluso automaticamente dal makefile principale di BUILD_PACKAGE .

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

Ciò fornisce una panoramica dei componenti di base di un file manifest e delle relative funzionalità.

È possibile accedere all'ultima versione del file manifest per la modifica gerrit di esempio all'indirizzo: https://android.googlesource.com/platform/frameworks/base/+/master/packages/Shell/tests/AndroidManifest.xml

Un'istantanea è inclusa qui per comodità:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

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

        <activity
            android:name="com.android.shell.ActionSendMultipleConsumerActivity"
            android:label="ActionSendMultipleConsumer"
            android:theme="@android:style/Theme.NoDisplay"
            android:noHistory="true"
            android:excludeFromRecents="true">
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
        </activity>
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
        android:targetPackage="com.android.shell"
        android:label="Tests for Shell" />

</manifest>

Alcuni commenti selezionati sul file manifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

L'attributo 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.

Poiché si tratta di un pacchetto dell'applicazione di test, indipendente dal pacchetto dell'applicazione sottoposto a test, è necessario utilizzare un nome di pacchetto diverso: una convenzione comune consiste nell'aggiungere un suffisso .test .

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

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

<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, pertanto richiede voci del percorso di classe aggiuntive quando il pacchetto di test viene richiamato dal framework dell'applicazione.

android:targetPackage="com.android.shell"

Questo imposta il pacchetto di destinazione della strumentazione su com.android.shell . Quando la strumentazione viene richiamata tramite il comando am instrument , il framework riavvia il processo com.android.shell e inserisce il codice della strumentazione nel processo per l'esecuzione del test. Ciò significa anche che il codice di test avrà accesso a tutte le istanze di classe in esecuzione nell'applicazione sottoposta a test e potrebbe essere in grado di modificare lo stato in base agli hook di test esposti.

File di configurazione semplice

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

File di configurazione complesso

Per test più complessi, devi anche scrivere un file di configurazione del test per il test harness di Android, Trade Federation .

La configurazione del test può specificare opzioni di configurazione del dispositivo speciali e argomenti predefiniti per fornire la classe di test.

È possibile accedere all'ultima versione del file di configurazione per la modifica di gerrit di esempio all'indirizzo: frameworks/base/packages/Shell/tests/AndroidTest.xml

Un'istantanea è inclusa qui per comodità:

<configuration description="Runs Tests for Shell.">
    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
        <option name="test-file-name" value="ShellTests.apk" />
    </target_preparer>

    <option name="test-suite-tag" value="apct" />
    <option name="test-tag" value="ShellTests" />
    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
        <option name="package" value="com.android.shell.tests" />
        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
    </test>
</configuration>

Alcune note selezionate sul file di configurazione del test:

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

Questo dice a Trade Federation di installare ShellTests.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="com.android.shell.tests"/>
  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>

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

Guarda qui per ulteriori informazioni sulle configurazioni 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 gerrit di esempio contiene un uso molto semplice delle sue funzionalità.

È possibile accedere al codice sorgente più recente per la modifica di gerrit di esempio all'indirizzo: frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java

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

@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {

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

L'annotazione @SmallTest specificato una dimensione del test per l'intera classe di test: tutti i metodi di test aggiunti a questa classe di test ereditano questa annotazione della dimensione del test. configurazione della classe pre-test, smontaggio post-test e smontaggio della classe post-test: simili ai metodi setUp e tearDown in JUnit4. L'annotazione del Test viene utilizzata per annotare il test effettivo.

    @Before
    public void setup() {
    ...
    @Test
    public void testGetProvider_shouldCacheProvider() {
    ...

L'annotazione @Before viene utilizzata sui metodi di JUnit4 per eseguire l'impostazione del test preliminare. Sebbene non sia utilizzato in questo esempio, c'è anche @After per lo smontaggio post test. Allo stesso modo, le annotazioni @BeforeClass e @AfterClass possono essere utilizzate sui metodi di JUnit4 per eseguire l'installazione prima di eseguire tutti i test in una classe di test e successivamente lo smontaggio. Si noti che i metodi di configurazione e smontaggio dell'ambito della classe devono essere statici.

Per quanto riguarda i metodi di test, a differenza della versione precedente di JUnit, non è più necessario iniziare il nome del metodo con test , ma ognuno 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.

        Context context = InstrumentationRegistry.getTargetContext();

Poiché i test JUnit4 non richiedono più una classe base comune, non è più necessario ottenere istanze Context tramite getContext() o getTargetContext() tramite i metodi della classe base; invece, il nuovo test runner li gestisce tramite InstrumentationRegistry dove è archiviata la configurazione contestuale e ambientale creata dal framework della strumentazione. Attraverso questa classe, puoi anche chiamare:

  • getInstrumentation() : l'istanza della classe Instrumentation
  • getArguments() : gli argomenti della riga di comando passati ad am instrument tramite -e <key> <value>

Crea e testa localmente

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

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