Cocoaheads Paris Nombembre Test unitaires

Preview:

Citation preview

Tests unitaires

Tests unitaires en Java pendant 2ans

Tests unitaires iOS pendant 2ans

La transition pique un peu…

Il était une fois un débutant…

=

Je passe 90% de mon temps à essayer de faire marcher UIKit comment les tests unitaires vont ils m’aider ?

Qui débuggait tout le temps...

J’utilise le debugger, et des logs

Et puis un jour…

Développer avec le debugger devient un frein

Debugger d’Xcode peu efficace (pas d’évaluation, variables non accessibles)

Faire du pas à pas dans le simulateur n’est pas productif

Comment détecter les impacts quand on refactor une méthode ?

Il se rend compte que :

Les tests unitaires sur iOS finalement ça marche

Et ça fait gagner du temps

C’est quoi le test unitaire de cette session ?

Sortirez vous d’ici prêt à écrire au moins un test d’ici la fin de l’année ?

AGENDA

Quel framework choisir ?

Un test simple

Où tester ?

Cas réel : appel de Web Service

Pour aller plus loin

Conclusion

Retour d’expérience

Des projets de bout en bout en TDD avec 3 différents Framework :

OCUnit

GTM

GHUnit

OCUnit, les pour

Intégré à Xcode

Stable

Pas de configuration

Se lance avec un raccourci clavier

OCUnit, les contre

Utilisation d’un bundle différent de l’application

Points d’arrêt en dehors des classes de tests

Impossible de lancer un seul test

Lance les tests en même temps que l’application

OCUnit, test de recette

Given :

developper.level = kBeginner; developper.objectives = kLow;

When

Framework *result = [develepper chooseUnitTestingFramework];

Then

assertThat(result, equalTo(OCUnit));

GTM, les pour

Target d’application pour les tests

Bien intégré à Xcode

Communauté active

Peu de limitations

GTM, les contres

Logs très difficilement exploitables

Ne gère pas bien les exceptions

GTM, test de recette

Given :

developper.level = kHigh; developper.objectives = kHigh;

When

Framework *result = [develepper chooseUnitTestingFramework];

Then

assertThat(result, equalTo(GTM));

GHUnit, les pours

Supporte les test écrits pour OCUnit et GTM

Logs sexy

Possibilité de lancé les tests individuellement

Très simple à mettre en place

GHUnit, les contres

Pas d’intégration à Xcode

Difficilement automatisable

S’exécute dans context de l’application sur un autre Thread Tried to obtain the web lock from a thread other than the main

thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...

GHUnit, test de recette

Given :

developper.level = kMedium; developper.objectives = kMedium;

When

Framework *result = [develepper chooseUnitTestingFramework];

Then

assertThat(result, equalTo(GHUnit));

AGENDA

Quel framework choisir ?

Un test simple

Où tester ?

Cas réel : appel de Web Service

Pour aller plus loin

Conclusion

Configurer OCUnit

Comment OCUnit fonctionne

Xcode créé : Une « application target » Un « test bundle target »

Faire attention aux choix de targets

Template standard : ce que l’on ne veut pas…

Interface

Template standard : ce que l’on ne veut pas…

Implementation

Template custom : ce que l’on veut !

Interface

Template custom : ce que l’on veut !

Implementation

Un template de méthode de test

Un exemple de test

AGENDA

Quel framework choisir ?

Un test simple

Où tester ?

Cas réel : appel de Web Service

Pour aller plus loin

Conclusion

ControllerView

Model

Views

ASIHTTPRequest

ViewControllers

Notre application

Objets métiers

Délégation

Requêtes asynchrone

JSON ParserServices

Tester quoi ?

Model Controller View

facile Complexe

ControllerView

Model

Views

JSON Parser

ASIHTTPRequest

ViewControllers

Tester quoi ?

Objets métiers

Services

Où tester ?

ServiceController-(void) loadArticlesFrom:To:

-(void) service:didSucceedWithArticles:

ASI

-(void) startAsynchronous

-(void) requestFinished:

Préparation de la requete

Traitement de la réponse

Où tester ?

Préparation de la requête :

Est ce que la bonne url est appelée avec les bons paramètres ?

Est ce que les bons paramètres sont envoyés dans le body ?

Eventuellement validation des paramètres

Où tester ?

Traitement de la réponse :

A partir du JSON est ce que j’alimente bien les objets de mon modèle ?

Les règles et la logique de traitement des articles est respectée ?• Si le status de l’article est … alors …

Si je reçois des liens est ce que je télécharge bien les données ?• Images, pdf, etc

Où tester ?

Chaine globale :

Est ce que j’appelle bien ASI ?

Est ce que je reçois la réponse de ASI ?

Est ce que j’appelle bien la méthode didSucceed / didFail de mon delegate ?

AGENDA

Quel framework choisir ?

Un test simple

Où tester ?

Cas réel : appel de Web Service

Pour aller plus loin

Conclusion

Tests des méthodes privées

ServiceTest

-(Request*) requestForArticlesPréparation de

la requete

Traitement du retour

-(NSArray*) parseData:(NSData*)

Tests des méthodes privées

Une implémentation complexe à tester :

Tests des méthodes privées

Pas de valeur de retour

Tests des méthodes privées

Appels de singletons

Tests des méthodes privées

Créer des méthodes qui prennent des paramètres simples à créer dans vos tests

Créer des méthodes qui retournent des objets simple à tester dans vos tests

Gérer l’asynchrone en dehors de ces méthodes

Pour plus d’informations voir le pattern « dependency injection »

http://spin.atomicobject.com/2010/12/09/objection-dependency-injection-in-obj-c/

Comment modifier légèrement votre code pour créer des situations faciles à tester

Tests des méthodes privées

Une méthode facile à tester :

Tests des méthodes privées

Une méthode facile à tester :

Tests des méthodes privées

Un exemple de test :

AGENDA

Quel framework choisir ?

Un test simple

Où tester ?

Cas réel : appel de Web Service

Pour aller plus loin

Conclusion

Pour aller plus loin

Une autre session ?

OCMock

Tests des méthodes assynchrones

CoreData

AGENDA

Quel framework choisir ?

Un test simple

Où tester ?

Cas réel : appel de Web Service

Pour aller plus loin

Conclusion

Conclusion

Privilégiez un Framework simple à un Framework complet

Peu de tests vaut mieux que pas de tests du tout

Dans certains cas développer en TDD est plus productif qu’avec le simulateur

Modifier légèrement votre code pour créer des situations faciles à tester

Take away

Pour récapituler :

Sortez la logique de vos controller

Identifier le code que vous souhaitez tester

Sortez le dans une méthode spécifique

Faites en sorte que cette méthode soit simple à tester