Esempio di test autostrumentali

Quando viene avviato un test della strumentazione, il relativo pacchetto di destinazione viene riavviato con il codice della strumentazione inserito e avviato per l'esecuzione. L'unica eccezione è che il pacchetto di destinazione qui non può essere il framework di applicazioni Android per sé, vale a dire il pacchetto android , perché così facendo avrebbe portato alla situazione paradossale in cui avrebbe bisogno di essere riavviato quadro di Android, che è ciò che sostiene le funzioni del sistema, compresa la strumentazione si.

Ciò significa che un test di strumentazione non può iniettarsi nel framework Android, noto anche come server di sistema, per l'esecuzione. Al fine di testare il quadro di Android, il codice di prova può invocare superfici API solo pubblici, o di quelli esposti tramite l'interfaccia di Android Definition Language AIDL disponibili nella struttura di origine piattaforma. Per questa categoria di test, non è significativo scegliere come target un particolare pacchetto. Pertanto, è consuetudine per tali strumentazioni da dichiarare di indirizzare il proprio pacchetto di applicazioni di test, come definito nel proprio <manifest> tag di AndroidManifest.xml .

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

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

Questa categoria di test strumentali viene talvolta definita autostrumentazione. Ecco alcuni esempi di test di autostrumentazione nel sorgente della piattaforma:

L'esempio qui trattato consiste nella scrittura di un nuovo test della strumentazione con il pacchetto di destinazione impostato sul 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 su una posizione di origine

In genere il tuo team avrà già un modello stabilito di posti per il check-in del codice e posti per aggiungere i 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 la vostra fonte componente è a <component source root> , la maggior parte dei componenti hanno src e tests cartelle sotto di essa, e alcuni file aggiuntivi, come Android.mk (o suddiviso in ulteriori .mk file), il file manifesto AndroidManifest.xml , e il file di configurazione di prova 'AndroidTest.xml'.

Dal momento che si sta aggiungendo un nuovo test, è probabilmente necessario creare il tests directory successiva al componente src , e popolarlo con i contenuti.

In alcuni casi, la vostra squadra potrebbe avere ulteriori strutture di directory sotto tests a causa della necessità di confezionare differenti suite di test in singoli APK. E in questo caso, è necessario creare una nuova directory sotto sotto tests .

Indipendentemente dalla struttura, si finirà per popolare il tests directory o la sottodirectory appena creata con file simili a ciò che è in instrumentation directory nel cambiamento Gerrit campione. Le sezioni seguenti spiegheranno in ulteriori dettagli di ciascun file.

File manifest

Proprio come una normale applicazione, ogni modulo di test della strumentazione necessita di un file manifest. Se è il nome del file come AndroidManifest.xml e fornirlo accanto al Android.mk per il modulo di test, si otterrà automaticamente inclusi dal BUILD_PACKAGE makefile nucleo.

Prima di procedere oltre, è altamente raccomandato di passare attraverso l' App manifesto Panoramica prima.

Questo fornisce una panoramica dei componenti di base di un file manifest e delle loro funzionalità. Vedere l'esempio a platform_testing / test / esempio / strumenti / 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>

Alcune note selezionate sul file manifest:

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

Il package attributo è il nome del pacchetto di applicazione: questo è l'identificatore univoco che utilizza il framework di applicazioni Android 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 package attributo è lo stesso di quello ComponentName#getPackageName() ritorna, e anche la stessa si usa per interagire con i vari pm comandi secondario via 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 dell'applicazione (o del test) 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 nell'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. Si noti che questo dipende dal APK essere firmato con stesso certificato come piattaforma centrale (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 richiede il system identità utente del chiamante, che richiede il pacchetto chiamando alla quota id utente con il system , se si tratta di un pacchetto separato dalla piattaforma di base in sé
<uses-library android:name="android.test.runner" />

Ciò è necessario 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="android.test.example.helloworld"

Potreste aver notato che il targetPackage qui è dichiarato lo stesso del package attributo dichiarato nel manifest tag di questo file. Come accennato in nozioni di base di test , questa categoria di test di strumentazione sono in genere destinata a testare le API quadro, quindi non è molto significativo per loro di avere un pacchetto di un'applicazione specifica mirata, altri poi 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 confezionamento. Nella maggior parte dei casi, l'opzione del file Blueprint basata su Soong è sufficiente. Per dettagli, vedere Configurazione di prova semplice .

File di configurazione complesso

Per questi casi più complessi, è inoltre necessario scrivere un file di configurazione di prova per il test harness di Android, Federazione dei Mercanti .

La configurazione del test può specificare opzioni di configurazione del dispositivo speciali e argomenti predefiniti per fornire la classe di test. Vedere l'esempio a /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>

Alcune note di selezione 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>

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

Per ulteriori informazioni, vedere Test Module Configs .

Funzionalità JUnit4

Utilizzando android-support-test biblioteca come prova corridore consente l'adozione di nuove classi di test stile JUnit4, e il cambiamento Gerrit campione contiene un certo uso molto di base delle sue caratteristiche. Vedere l'esempio a /platform_testing/tests/example/instrumentation/src/android/test/example/helloworld/HelloWorldTest.java .

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

@RunWith(JUnit4.class)
public class HelloWorldTest {

Una differenza significativa in JUnit4 è che i test non devono più ereditare da una classe di test di base comune; invece, scrivi i test in classi Java semplici e usi l'annotazione per indicare determinate impostazioni e vincoli del test. In questo esempio, stiamo indicando che questa classe deve essere eseguita come 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() {
    ...

I @Before e @After annotazioni vengono utilizzati metodi di JUnit4 effettuare configurazione di prova pre e post teardown prova. Analogamente, i @BeforeClass e @AfterClass annotazioni vengono utilizzati metodi di JUnit4 per eseguire la configurazione prima di eseguire tutti i test in una classe di test, e successivamente smontaggio. Si noti che i metodi di impostazione e smontaggio dell'ambito della classe devono essere statici. Per quanto riguarda i metodi di prova, a differenza della versione precedente di JUnit, non hanno più necessità di 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 prova si sono annotati con @Test annotazioni; e nota che i test siano eseguiti attraverso APCT, devono essere annotate con dimensioni di prova: l'esempio annotato metodo testHelloWorld come @SmallTest . L'annotazione può essere applicata nell'ambito del metodo o nell'ambito della classe.

Accesso instrumentation

Per quanto non contemplato nel esempio di base ciao mondo, è abbastanza comune per un test di Android per richiede l'accesso Instrumentation esempio: questo è l'interfaccia API di base che fornisce l'accesso a contesti applicativi, le API di prova relativi al ciclo di vita di attività e di più.

Poiché il JUnit4 test non richiede una classe base comune, non è più necessario per ottenere Instrumentation esempio tramite InstrumentationTestCase#getInstrumentation() , invece, il nuovo test runner lo gestisce tramite InstrumentationRegistry in cui è memorizzato l'installazione contestuale ed ambientale creato da quadro strumentazione.

Per accedere alla istanza della Instrumentation di classe, è sufficiente chiamare il metodo statico getInstrumentation() su InstrumentationRegistry classe:

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

Crea e testa in locale

Per la maggior parte dei casi di uso comune, impiego Atest .

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