• Programmazione Android
  • CORSI ONLINE
  • Web Agency

Logo

Corsi di programmazione web e mobile online
Navigation
  • Home
  • CORSI ONLINE
  • Tutorial Pratici
  • GUIDE COMPLETE
    • Corso completo di C
    • Corso videogame con Cocos2d
    • Programmazione Cocoa Touch
  • Sezioni
    • Libri e manuali
    • Tips & Tricks
    • Risorse utili
    • Strumenti di Sviluppo
    • Materiale OpenSource
    • Framework
    • Guide Teoriche
    • Guide varie
    • Grafica e Design
    • iPad
    • News
    • Video Tutorial
    • Windows Phone
  • Pubblicità
  • About
    • Chi siamo
    • Pubblicazioni
    • Collabora
    • Sostieni devAPP

Uno sguardo a Unit test: impariamo a prevenire ore e ore di debug durante lo sviluppo di Applicazioni iOS

By IgnazioC | on 8 Agosto 2011 | 2 Comments
Senza categoria

unit-test-xcode-devapp In questo articolo vedremo come effettuare un test del nostro codice sorgente utilizzando Unit Test. Per chi non ne fosse a conoscenza i test sono alla base di un modello di sviluppo chiamato, appunto, test-driven development e ne sono tanto alla base, che le procedure di test vengono scritte addirittura prima del codice da testare.
Non chiedetemi se sono favorevole a questo approccio; i miei brevi studi sulla calcolabilità e decidibilità mi fanno inorridire (e avrebbero fatto inorridire anche A.Turing (link) all’idea di dimostrare il corretto funzionamento di un programma tramite un altro programma, ma se ridimensioniamo le aspettative e diciamo che i test non servono a dimostrare che un programma funzioni ma semplicemente per verificare che l’output prodotto a parità di input segua le nostre aspettative.. beh allora direi che tutto si fa più interessante.

Per chi non avesse difficoltà con l’inglese consiglio una lettura a questo articolo: è l’articolo dal quale ho preso spunto per scrivere questo testo che vi accingete a leggere. Tengo a precisare che la mia non vuole essere una semplice traduzione dell’articolo originale, ma reputo anche giusto sottolineare che non è tutta farina del mio sacco e una citazione alla fonte sicuramente male non farà.

Prima di addentrarci nel nostro articolo vediamo brevemente il significato di alcuni termini:

  • test case: Un singolo test usato per verificare una particolare funzionalità software.
  • test suite: Un insieme di test case che verificano il comportamento di una porzione più ampia di codice.
  • logic tests: Sono i test che non vengono eseguiti all’interno di un’applicazione vera e propria. Si possono scrivere logic test e far sì che vengano eseguiti in fase di compilazione. Questo assicura al test una certa indipendenza dall’applicazione finale
  • application tests: Per convesso sono i test che vengono eseguiti all’interno di un’applicazione realmente funzionante. Sono eseguiti quindi a runtime non a compile-time. (non verranno presi in esame in questo articolo)

Come aggiungere un logic test al nostro software?

Xcode 4 prevede già la possibilità di aggiungere, in fase di creazione del progetto, tutto quanto necessario per creare un unit test, ma per assicurarci una maggiore comprensione partiremo da un progetto vuoto.

Creiamo quindi un nuovo progetto, io l’ho chiamato “TestOC”, perché il framework per effettuare i test si chiama “OCUnit”. Ok, ok… l’idea di inserire la parola “test” nel nome del progetto non è stata proprio felicissima 🙂
Creato il progetto bisogna aggiungere un nuovo unit-test bundle target e per farlo basta selezionare dentro Xcode l’icona del progetto e cliccare sul pulsante “Add target” presente sulla destra. Selezioniamo quindi “Cocoa Touch Unit Testing Bundle” dalla schermata che appare e diamogli un nome significativo.





A questo punto dovreste trovarvi con una struttura di file simile a questa:



dove si può notare che xCode ha già creato per noi sia i file necessari per la compilazione, sia una classe “TestOCLogicTest” dove poter scrivere i nostri test.

Se la vostra versione di xCode non dovesse aggiungere questa classe basterà aggiungerla manualmente tramite la solita procedura “file -> new->new file” selezionando il tipo “Objective-c Test case Class” e facendo attenzione di spuntare la casella solo per il target di testing.



Se xcode ha creato per voi la classe “TestOCLogicTest” avrà inserito all’interno una serie di metodi standard, per il momento commentateli ed aggiungete nel file .m questo codice:

- (void) testFail {
STFail(@"Must fail to succeed.");
}

Selezionate lo schema appropriato usando il simulatore come device e cliccare sul pulsante “Test”, vedrete la vostra compilazione fallire miseramente con questo messaggio:



Cosa è successo? Xcode ha effettuato il test del nostro codice, nello specifico ha eseguito il metodo “testFail” della classe “TestOCLogicTest” che ha come unico scopo quello di far fallire il test.

Adesso facciamo un’altra prova e sostituiamo il metodo che abbiamo appena scritto con questo:

- (void) testPass {
STAssertTrue(TRUE, @"");
}

Cosa succederà eseguendo il test? Apparentemente nulla, xcode dirà “compilazione andata a buon fine” senza ulteriori dettagli, però se andiamo a guardare i messaggi di log nella console vedremo una serie di informazioni molto utili.



Se proprio siete curiosi potete provare ad inserire entrambi i metodi nella classe, noterete che vengono eseguiti tutti e due, indipendentemente dal loro ordine e sulla console viene mostrato un report di cosa è successo:



Scriviamo i nostri test

Ma cos’è in soldoni un test? È un metodo di istanza di una classe “SenTestCase” che non ha parametri, il suo nome inizia per test… e non ha nessun valore di ritorno. All’interno di questi metodi andremo and inizializzare i nostri oggetti e verificheremo se tutto è andato a buon fine usando le Unit-Test macro. Chiaro, no?

Un caso concreto

Giusto per chi non avesse afferrato tutto tutto… descriviamo una situazione tipica:
Abbiamo creato una nostra classe (MyClass) che viene inizializzata prelevando alcuni valori da un file xml, ad esempio con un metodo simile a questo:

-(id)initWithContentOfFile:(NSString *)filename {
NSBundle *thisBundle = [NSBundle bundleForClass:[self class]];
NSString *filePath = [thisBundle pathForResource:filename ofType:@"plist"];
	
NSString *filePath = [[NSBundle mainBundle] pathForResource:filename ofType:@"plist"];
	NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];
	if ([dict objectForKey:@"Name"]) {
		self = [super init];
		if (self) {
self.name = [dict objectForKey:@"Name"]
}
	}
	else {
self = nil;
	}
	return self;
}

Benissimo, in questo modo siamo sicuri che la nostra classe sarà consistente con l’idea che abbiamo in testa.

Facciamo adesso un balzo in avanti di qualche mese, avete assolutamente dimenticato questo aspetto un pò particolare di questa classe e, visto che sono cambiate le specifiche, tra le altre 100 modiche fatte al codice qualcuno ha anche deciso di cambiare nel file plist la chiave che da “Name” è diventata “Nome”… e ora stranamente il programma non funziona più…suona familiare? Quanto debug sarà necessario prima di capire che la classe “MyClass” non può essere istanziata con quel file plist e quindi risulta essere nil?

Risolviamo il nostro problema con unit test

Il programma non funziona perché sono venute meno le precondizioni che avevamo stabilito? Ma questo è un lavoro per unit test! Quando abbiamo scritto per la prima volta il nostro metodo “initWithContentOfFile” avremmo potuto scrivere un test case per questo metodo, così adesso che sono cambiate le precondizioni sicuramente il test ci avrebbe avvertito! Ma come creiamo quindi il test? Potremmo scrivere un test simile a questo:

-(void)testCreationMyClassIstance {
NSString *filename = @"preferences";
	MyClass *c = [[MyClass alloc] initWithContentOfFile:filename];
	STAssertNotNil(c, @"MyClass non è stata inizializzata");
}

nel quale creiamo una istanza della classe “MyClass” e poi usiamo la macro “STAssertNotNil” per verificare che non sia nil.

Se questo test viene eseguito prima di fare la modifica al file plist vediamo che l’esito è positivo:



mentre se invece effettuiamo maldestramente una modifica al file plist otteniamo immediatamente un comodissimo messaggio d’errore



Alla prossima!
IgnazioC

Share this story:
  • tweet

Tags: Cocoa Touch Unit Testing BundleDebug XCodeGuide varieIgnazio CalòOCUnitSviluppo applicazioni iphone e ipadtutorial XcodeUnit testunit-test bundle target

Recent Posts

  • Parte il percorso programmatori iOS in Swift su devACADEMY.it

    20 Dicembre 2017 - 0 Comment
  • Android, crittografare dati velocemente con Encryption

    24 Settembre 2018 - 0 Comment
  • Sql2o, accesso immediato ai database tramite Java

    3 Settembre 2018 - 0 Comment
  • Okio, libreria per ottimizzare l’input/output in Java

    27 Agosto 2018 - 0 Comment

Related Posts

  • Come creare mock API per le nostre applicazioni

    2 Giugno 2015 - 1 Comment
  • Xcode 4: Distribuzione Ad Hoc delle applicazioni iPhone e iPad

    10 Gennaio 2012 - 20 Comments
  • Tutorial pratici per iOS SDK: disponibile la versione 2.0 aggiornata a iOS 5 e XCode 4.2

    16 Novembre 2011 - 6 Comments

Author Description

2 Responses to “Uno sguardo a Unit test: impariamo a prevenire ore e ore di debug durante lo sviluppo di Applicazioni iOS”

  1. 8 Agosto 2011

    ignazioc

    andateci piano con le critiche…sono nuovo dell’argomento…

  2. 12 Agosto 2011

    Luca Degasperi

    Un passo alla volta, è importante dire che se si vuole seguire la filosofia TDD i test non sono più solo una comodità ma un obbligo. E quindi non devono essere visti come uno spreco di tempo, o una cosa giusto per fare contento il capo / cliente. O si fanno bene o non si fanno! Inoltre sempre secondo le specifiche TDD vanno scritti PRIMA i test e DOPO il codice che dovrà superare i test. Questo non solo aiuta a fare chiarezza nel codice ma anche all’interno della mente di chi programma e del gruppo di lavoro di qui si fa parte.

Leave a Reply

Your email address will not be published. Required fields are marked *


*
*

Corso online di programmazione android e java

SEZIONI

  • Android
  • Comunicazioni
  • Contest
  • Corsi ed Eventi
  • Corso completo di C
  • Corso programmazione videogiochi
  • Framework
  • Grafica e Design
  • Guida rapida alla programmazione Cocoa Touch
  • Guide Teoriche
  • Guide varie
  • iPad
  • Le nostre applicazioni
  • Libri e manuali
  • Materiale OpenSource
  • News
  • Pillole di C++
  • Progetti completi
  • Risorse utili
  • Strumenti di Sviluppo
  • Swift
  • Tips & Tricks
  • Tutorial Pratici
  • Video Tutorial
  • Windows Phone

Siti Amici

  • Adrirobot
  • Allmobileworld
  • Apple Notizie
  • Apple Tribù
  • Avvocato360
  • Blog informatico 360°
  • bubi devs
  • fotogriPhone
  • GiovaTech
  • iApp-Mac
  • iOS Developer Program
  • iPodMania
  • MelaRumors
  • Meritocracy
  • SoloTablet
  • TecnoUser
  • Privacy & Cookie Policy
©2009-2018 devAPP - All Rights Reserved | Contattaci
devAPP.it è un progetto di DEVAPP S.R.L. - Web & Mobile Agency di Torino
Str. Volpiano, 54 - 10040 Leini (TO) - C.F. e P.IVA 11263180017 - REA TO1199665 - Cap. Soc. € 10.000,00 i.v.

devACADEMY.it

Vuoi imparare a programmare?

Iscriviti e accedi a TUTTI i corsi con un’unica iscrizione.
Oltre 70 corsi e migliaia di videolezioni online e in italiano a tua disposizione.

ISCRIVITI SUBITO