Test con JUnit

28 novembre 2016

Come accennato nella lezione precedente, possiamo prevedere l’uso di unit test su un nuovo progetto di Android Studio come segue:

  • inserendo nel modulo applicativo la dipendenza a JUnit per la compilazione dei test:
    dependencies {
        ...
        testCompile 'junit:junit:4.12'
        ...
    }
    
  • predisponendo apposite classi all’interno della cartella java

    Figura 1. Organizzazione di un progetto in Android Studio (click per ingrandire)

    Organizzazione di un progetto in Android Studio

La classe predisposta per i test unitari sarà simile alla seguente (il cui contenuto ha qui carattere esemplificativo):

public class ExampleUnitTest {

    @Test
    public void addition_test() throws Exception {
        assertEquals(4, 2+2);
    }
}

Si tratta di una classe Java, il cui unico metodo ha due caratteristiche particolari:

  • l’annotazione @Test, messa a disposizione da JUnit per indicare che quel metodo rappresenta un test (possiamo usare tale annotazione in quanto abbiamo incluso JUnit4: fino alla versione 3, invece, i metodi di questo genere avevano un nome con prefisso “test”);
  • il metodo assertEquals, che implementa il testo vero e proprio. In questo esempio, tale test consiste nel confrontare due valori, e si considera passato se essi risultano uguali. In generale, il primo parametro è il valore che ci si aspetta ottenere, mentre il secondo parametro generalmente invoca un metodo o alcune operazioni annidate, il cui risultato dovrebbe essere uguale al primo.

Per eseguire il test, su Android Studio dovremo agire tramite menu:

Figura 2. Eseguire test in Android Studio (click per ingrandire)

Eseguire test in Android Studio

Al termine dell’esecuzione, Android Studio mostrerà il risultato.

Figura 3. Risultato dei test in Android Studio (click per ingrandire)

Risultato dei test in Android Studio

Dall’immagine qui riportata, emerge che il test è stato eseguito su Java Virtual Machine, è durato 2 ms ed è stato portato a termine correttamente: tra l’altro, il successo del collaudo ci viene visivamente confermato anche dal colore verde della banda. Inseriamo ora un test destinato a fallire, aggiungendo il metodo seguuente:

@Test
public void test_boolean() throws Exception {
     assertTrue(false);
}

Usiamo un’altra delle assertion di JUnit, ovvero assertTrue, che verifica se il valore passato corrisponde al true booleano. Poichè passiamo false come parametro, il test fallirà e Android Studio mostrerà un risultato simile al seguente:

Figura 4. Fallimento di un test (click per ingrandire)

Fallimento di un test

Ci viene segnalato che due test sono stati eseguiti ed uno è fallito. Anche i colori associati ai singoli test hanno un significato particolare:

  • verde: il test ha avuto successo;
  • giallo: l’esecuzione non ha riscontrato problemi ma il test non ha avuto successo perchè, ad esempio, il valore ottenuto è diverso da quello atteso;
  • rosso: durante il test è fallita l’esecuzione del codice, per esempio per via di in un’eccezione non gestita.

Unit test in un progetto Android

Supponiamo di avere un’app in cui l’interfaccia grafica permetta di registrare dati personali di individui. Per ognuno di essi, vengono raccolti una serie di informazioni – nome, cognome, età e se è automunito – e salvati in oggetti appartenenti alla classe Persona, definita come segue:

public class Persona {
    private String nome;
    private String cognome;
    private int eta;
    private boolean automunito;

    // OMISSIS: metodi getter e setter

}

Tramite il form dell’interfaccia grafica, creiamo degli oggetti Persona e li inseriamo nella classe DataManager, che li custodisce in un ArrayList in maniera non persistente:

public class DataManager {

    private ArrayList elenco=null;
    
    void nuovoInserimento(Persona nuovo)
    {
	elenco.add(nuovo);
    }

    int numeroInserimenti()
    {
        return elenco.size();
    }

    void cancellaPersona(int pos)
    {
        if (numeroInserimenti()>0 && pos<elenco.size())
            elenco.remove(pos);
    }

}

Il funzionamento dell’app è fortemente legato a quello di DataManager, classe che opera in maniera autonoma dialogando con il resto dell’applicazione mediante l’interfaccia offerta dai propri metodi. Questa è una situazione ideale per svolgere un test unitario. Aggiungiamo i metodi necessari all’interno della classe ExampleUnitTest che Android Studio ha già predisposto. Creeremo due test: il primo, test_inserimento, inserirà tre oggetti fittizi nella classe DataManager e ne verificherà il numero; il secondo, test_cancellazione, effettuerà la stessa verifica ma dopo averne cancellato uno:

public class ExampleUnitTest {
    @Test
    public void test_inserimento() throws Exception {
        DataManager dm = new DataManager();
        dm.nuovoInserimento(new Persona("Giulio", "Rossi", 34, true));
        dm.nuovoInserimento(new Persona("Paolo", "Verdi", 25, false));
        dm.nuovoInserimento(new Persona("Silvio", "Bianchi", 63, true));

        assertEquals(3, dm.numeroInserimenti());
    }

    @Test
    public void test_cancellazione() throws Exception {
        DataManager dm = new DataManager();
        dm.nuovoInserimento(new Persona("Giulio", "Rossi", 34, true));
        dm.nuovoInserimento(new Persona("Paolo", "Verdi", 25, false));
        dm.nuovoInserimento(new Persona("Silvio", "Bianchi", 63, true));
        
        dm.cancellaPersona(1);

        assertEquals(2, dm.numeroInserimenti());
    }
}

L’immagine seguente mostra che i test hanno entrambi successo:

Figura 5. Successo di tutti i test (click per ingrandire)

Successo di tutti i test

Proviamo a modificare in maniera erronea la classe DataManager, cambiando l’operatore di confronto all’interno del costrutto if:

 void cancellaPersona(int pos)
    {
	// metodo sbagliato!
        if (numeroInserimenti()<0)
            elenco.remove(pos);
    }

L'esecuzione del medesimo test rileverà quanto segue:

Figura 6. Un test rileva dei problemi (click per ingrandire)

Un test rileva dei problemi

Come possiamo vedere, uno dei due test sarà errato in quanto il valore ottenuto dall'invocazione del metodo numeroInserimenti è 3 (visto che la cancellazione non ha funzionato), mentre quello atteso è 2.

È facile immaginare che sarà necessario pianificare una strategia di test molto più estesa di quelle viste negli esempi di questa lezione, come sarà discusso nelle prossime lezioni.

Tutte le lezioni

1 ... 63 64 65 ... 85

Se vuoi aggiornamenti su Test con JUnit inserisci la tua e-mail nel box qui sotto:
Tags:
 
X
Se vuoi aggiornamenti su Test con JUnit

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy