Oltre a ricchezza di funzioni ed efficacia, un'app deve poter garantire una buona resistenza ai malfunzionamenti, sotto ogni condizione di utilizzo, nonchè piena rispondenza ai requisiti del progetto iniziale. La fase di debug è quindi indispensabile per la correzione di difetti durante lo sviluppo, ma
per poter essere certi dell'affidabilità del nostro software è necessario ricorrere alla pianificazione di una strategia di testing, mirata ed eseguita automaticamente. Con questa lezione iniziamo a vedere i fondamenti teorici del testing e a scoprire come Android Studio, con la sua configurazione flessibile, ci offra la possibilità di integrarli molto velocemente.
Iniziare con il testing: quando farlo e quali vantaggi ha
Il testing (o collaudo) di un'applicazione deve poter trovare una propria collocazione nel processo che conduce dall'idea iniziale alla distribuzione al pubblico, universalmente conosciuto come ciclo di vita del software. Il collaudo non dovrebbe mai essere considerato opzionale, ma in quale fase dello sviluppo va effettuato? Esistono più scuole di pensiero. L'approccio più tradizionale
vede il testing relegato alla fine dello sviluppo, in una condizione laterale, che a volte per tempistiche di consegna e impiego delle risorse si trova ad essere ridimensionata se non saltata del tutto. Altra filosofia di pensiero nonchè di organizzazione è il cosiddetto Test Driven Developement, procedimento per cui è il collaudo a guidare lo sviluppo, in maniera tale che il codice scritto abbia come primo scopo il superamento dei test.
I vantaggi dell'automazione dei test sono molti, ma cerchiamo di individuarne almeno i principali:
- la pianificazione di una strategia permette di applicare un'attività di test completa, come completo deve essere il soddisfacimento dei requisiti del software. Pianificando i test saremo sufficientemente certi di verificare tutte le funzionalità;
- il lavoro di verifica sarà molto minuzioso, e lo stesso codice sarà verificato più volte, su valori differenti. Ad esempio, se una determinata funzionalità deve lavorare su un array, dovrebbe essere in grado di fornire risultati o indicazioni in ogni condizione: array vuoto, array pieno, un solo valore, valori eterogenei, e così via;
- un collaudo ben pianificato è ripetibile. Ogni volta che modifichiamo il nostro programma, rischiamo potenzialmente di
introdurre malfunzionamenti. Un collaudo automatico e ripetibile può essere "lanciato" dopo ogni sessione di modifica per verificare le nuove funzionalità e per appurare la conservazione di quelle realizzate in precedenza. Si consideri anche che il testing, in quanto automatico, può - se le tecnologie software lo permettono - essere attivato anche in orari notturni o festivi in cui i programmatori non sono al lavoro; - il testing automatico può essere gestito da macchine e non da essere umani, e può quindi essere svolto senza distrazioni ed errori umani.
Terminologia del testing
Il collaudo del software è una delle tematiche più estese dell'Ingegneria del Software, pertanto non ci interessa in questa sede dilungarci in classificazioni troppo specifiche. Pensiamo piuttosto a fissare i concetti pricipali dell'argomento, di cui avremo bisogno nel seguito.
Innanzitutto, su Android i test possono essere eseguiti sia su Java Virtual Machine sia su dispositivo (reale o emulato). Nel primo caso, si riferiscono per lo più alla verifica del codice Java in sè stesso e non tanto alla sua interazione con il dispositivo; nel secondo caso, i test vengono eseguiti su device, offrendo quindi l'opportunità di una verifica completa delle funzionalità.
Inoltre, i test possono essere differenziati in base all'area di attività che ricoprono. La tipologia più basilare comprende i test unitari (o unit test). Si occupano di collaudare una singola funzionalità o classe, valutandone il lavoro isolatamente. Lo strumento più conosciuto per la loro realizzazione è la libreria JUnit. Sono solitamente i test più numerosi in una strategia di testing, in quanto vanno minuziosamente a verificare la correttezza dei singoli algoritmi. Via via che si vuole approfondire il funzionamento del software nel suo complesso, i test unitari non sono più sufficienti, pertanto si arriva a tipologie più evolute come gli integration test, che verificano l'azione congiunta di più elementi, ed i test funzionali, che cambiano punto di vista partendo dalle possibili interazioni dell'utente con il software piuttosto che da una porzione di codice. Queste ultime tipologie sono necessariamente chiamate in causa quando si vogliono collaudare le interfacce utente.
Test in Android Studio
Tra i principali obiettivi di Android Studio, c'è quello direndere il più possibile immediato il testing delle applicazioni. Per questo motivo, quando si crea un nuovo progetto troviamo tre package all'interno della cartella java del modulo app (quello di default), uno relativo al codice e due ai test:
- main: il codice della nostra applicazione;
- test: sono test che vengono eseguiti direttamente sulla Java Virtual Machine (JVM) e sono il modo più pratico per poter predisporre uno unit test con JUnit. Il vantaggio principale di averli in questa posizione consiste nell'immediatezza della loro esecuzione;
- androidTest: contiene test instrumented, eseguiti su dispositivo e attivati mediante le Instrumentation API. Questi test permettono di svolgere il collaudo di vari aspetti dell'applicazione sul suo funzionamento interno e la fruibilità dell'interfaccia utente. Come tipologia, gli Instrumented Test sono di integrazione o funzionali.
L'aspetto su cui Android Studio fa leva per poter integrare così bene nel medesimo progetto lo sviluppo dell'app ed i test è Gradle, il motore di build automation su cui si basa, e ciò per almeno due motivi. Il primo è la gestione delle dipendenze che, condotta in stile Maven, mette rapidamente a disposizione ciò di cui abbiamo bisogno. Ad esempio, per utilizzare JUnit non dovremo fare altro che inserirlo nel blocco dependencies
interno al file build.gradle del modulo applicativo:
dependencies {
...
testCompile 'junit:junit:4.12'
...
}
dove testCompile
indica che la dipendenza in questione verrà inclusa nel processo di compilazione dei test. Altro contributo offerto da Gradle è la possibilità di diversificare le tipologie di build. I tipi più comuni di build, i cosiddetti build type, sono due: debug e release. Tutti test, di default, rientrano nel build type debug.
Dopo aver compreso i concetti basilari del testing ed i primi rudimenti applicativi in Android Studio, nelle prossime lezioni vedremo qualche esempio pratico.