Post on 09-Jan-2017
#LinkValue #TheGreatPlaceToGeek
Tester c’est douter !
meetup 5 octobre 2016
Test: définition et utilisation
LinkValue #TheGreatPlaceToGeek
Tester, c’est douter ?● Evidemment !
● Tout le monde teste son code
● Test de faisabilité (poc)
● Vérification pendant le développement
● Recette
LinkValue #TheGreatPlaceToGeek
Test automatisé● C’est un code qui vérifie la validité d’un autre
● C’est un code qui surveille les régressions
● C’est un code dont l'exécution ne nécessite pas l'intervention d'un humain
LinkValue #TheGreatPlaceToGeek
Pourquoi écrire des tests ?Plus-value à court terme:
● Les tests rassurent
● Ils aident au développement
● Ils permettent certaines vérifications impossibles en manuel
LinkValue #TheGreatPlaceToGeek
Pourquoi écrire des tests ?Plus-value à moyen terme:
● VSR et VABF plus court
● Facilite l’implémentation de nouvelles fonctionnalités
● Limite voir supprime les régressions
● Facilite la migration et la refactorisation
LinkValue #TheGreatPlaceToGeek
Pourquoi écrire des tests ?Plus-value à long terme:
● Limite la dette technique
● Accélère la vitesse de développement
● Surveille/ évite le retour des bugs corrigés ● Coût des bugs amoindri
LinkValue #TheGreatPlaceToGeek
Coût des bugs
Unitaire, Intégration, Fonctionnel
LinkValue #TheGreatPlaceToGeek
Le test unitaire● Teste unitairement une portion de code
● Assure le bon fonctionnement d’une méthode
● Mock de toutes les dépendances
● Test à granularité fine
● Test de type white box
LinkValue #TheGreatPlaceToGeek
Le test d’intégration● Teste l’assemblage de plusieurs composants logiciels indépendants
● Ne vérifie pas la conformité des composants
● Assure la cohésion d’un système
● Test à granularité moyenne
● Test de type white box
LinkValue #TheGreatPlaceToGeek
Le test fonctionnel● Simule l’action d’un utilisateur
● Ne tient pas compte des différentes couches applicatives
● Vérifie le résultat général
● Test à grosse granularité
● Test de type black box
LinkValue #TheGreatPlaceToGeek
Vue globale
Les tests doubles
LinkValue #TheGreatPlaceToGeek
Fonctionnement d’un test
● Un test appelle un SUT
● SUT : System Under Test
● Si le SUT possède des dépendances, on les Mocks
● … ou on les Stubs
LinkValue #TheGreatPlaceToGeek
Définition d’un Stub● Un Stub est centré sur le SUT
● Il lui fournit une indépendance
● Il lui fournit des données utilisées pendant les tests
● Il ne fait jamais échouer le test
● “State-based testing”
LinkValue #TheGreatPlaceToGeek
Définition d’un Stub● Un Stub est centré sur le SUT
● Il lui fournit une indépendance
● Il lui fournit des données utilisées pendant les tests
● Il ne fait jamais échouer le test
● “State-based testing”
LinkValue #TheGreatPlaceToGeek
Définition d’un Mock● Un Mock est centré sur le test
● Il décide si le test échoue ou réussit
● Une assertion se fait contre le Mock
● On ne teste pas le résultat mais la manière de l’obtenir
● “Interaction testing”
LinkValue #TheGreatPlaceToGeek
Définition d’un Mock
LinkValue #TheGreatPlaceToGeek
Les autres tests doubles
● Dummy : passer en paramètre à l’objet mais n’est jamais appelé
● Fake : l’objet possède une implémentation simple qui retourne toujours le même résultat
● Spy : objet qui surveille le comportement d’un code ne pouvant être relevé
LinkValue #TheGreatPlaceToGeek
On s’en mock
● Dummy, spies, fake sont des cas spécifiques de mocks ou de stubs
● Comprendre et maitriser l’utilisation des mocks et des stubs induit l’utilisation des autres sans en avoir pleinement conscience
● De toute facon, par abus de language, on appelle tout un “mock”
Bonnes Pratiques
LinkValue #TheGreatPlaceToGeek
Avant-propos :Tests smellsTest smells définit tout type de test qui ne valide pas la qualité du code
et/ou gène le travail du développeur.
● Test difficile à comprendre et à maintenir.
● Test trop long.
● Test un faux positif ou faux négatif.
● Test avec effet de bord.
● Test multiple comportement en une fois.
LinkValue #TheGreatPlaceToGeek
● Mock toutes les dépendances
● Seule la classe testée doit être instanciée
● Tester une classe, une méthode et un comportement à la fois
● Si plusieurs comportements par méthode, faire un test pour chacun
Un test unitaire doit être unitaire
LinkValue #TheGreatPlaceToGeek
Un test unitaire doit être rapide
● Il teste la vitesse d’éxécution du script
● Ne dialogue avec personne (bdd, classe tiers, webservice …)
● Confort pour le développeur (lancer tous les tests avant chaque commit)
LinkValue #TheGreatPlaceToGeek
Un code doit toujours être testable
● Indicateur de fiabilité
● Indicateur de refactoring
LinkValue #TheGreatPlaceToGeek
CODEZ PROPRE !!!● Les tests sont le reflet de l’application
● Ils doivent être compréhensibles et maintenables
● Evite le risque de “test smell”
● Non, ce n’est pas qu’un test
● Oui, c’est grave
LinkValue #TheGreatPlaceToGeek
Testez vos cas d’erreurs
● Faites un test pour chaque cas d’erreur
● Vérifiez la nature de la réponse (boolean, exception … )
● Vérifiez le comportement de vos catch dans le cas d’un try/catch
LinkValue #TheGreatPlaceToGeek
Une seule méthode par test
● Plus simple à maintenir
● Granularité plus fine en cas de débbugage
LinkValue #TheGreatPlaceToGeek
Code: Tests:
LinkValue #TheGreatPlaceToGeek
Nommer proprement vos tests
● Indiquez la méthode testée dans le nom du test : “testMyCustomMethod”
● Indiquez le use case dan le nom du test: “testMyCustomMethodWithSecondParametersMissing”
● Le nom du test doit indiquer son comportement
LinkValue #TheGreatPlaceToGeek
Identifiez précisement les étapes
● SetUp: équivalent à un construct
● Exercise: déroulement logique du texte
● Verify: contrôle le résultat
● TearDown: équivalent à destruct
LinkValue #TheGreatPlaceToGeek
Ne laissez pas de traces
● Ajoutez et supprimez les données de test durant les phases de SetUp et TearDown
● Ne vous appuyez pas sur les fixtures
● Toujours remettre votre base de donnée à l’état initiale à la fin de chaque test
LinkValue #TheGreatPlaceToGeek
Gérez vos données
● Les intéractions avec la base de données doivent être testées lors de tests fonctionnels
● Recréez votre database et vos fixtures avant de lancer vos tests
LinkValue #TheGreatPlaceToGeek
Vos tests sont des classes comme les autres
● Stockez vos paramètres et dépendances dans des attributs
● Découplez vos méthodes réutilisables (DRY)
● Utilisez les principes SOLID
LinkValue #TheGreatPlaceToGeek
LinkValue #TheGreatPlaceToGeek
Ne vous focalisez pas sur le code coverage, mais gardez un ratio de 100% mininum
● 100% ne couvre pas tous les cas de figure
● Moins, c’est la certitude de ne pas couvrir “du tout” une partie du code
● Si moins de 100, alors combien et pourquoi ?
● C’est mettre en péril la valeur qualitative des tests
LinkValue #TheGreatPlaceToGeek
Aucun test n’est futile● Tester vos Models
● Tester vos getters et setters
● Oui ca sert (principalement en TDD)
● Ca prend cinq minutes à écrire
* attention : aucun test n’est futile! Mais il est inutile de tester le code qui ne vous appartient pas (librairie tierce/framework …)
LinkValue #TheGreatPlaceToGeek
N’écrivez pas les tests à la fin
● Ecrivez vos tests durant le développement
● Un test est plus simple à écrire quand le code est récent
● Il illustre la mise en pratique du code
● Il complète la doc
● Il limite les “tests smells”
LinkValue #TheGreatPlaceToGeek
Evitez les valeurs fixes
● Sauf si c’est dans les specs
● Les tests ne doivent pas bloquer l’évolution du code
● Cela provoque un couplage avec le code
LinkValue #TheGreatPlaceToGeek
Evitez la logique
● Pas de boucle ou de conditions dans un test
● Utilisez les dataProviders pour jouer le test avec plusieurs valeurs
● Simplifiez la compréhension de vos tests
LinkValue #TheGreatPlaceToGeek
Mauvaises idées
● Modifier les paramètres d’environnement pour faire passer certains tests
● Certains tests ne fonctionnent pas partout
● Mon test unitaire est long car …
● Certains tests sont aléatoirement en échec
Cas pratique
LinkValue #TheGreatPlaceToGeek
Mise en situationContexte:
1. On récupère depuis un api externe des données utilisateurs
2. On enregistre les données en base via un orm
3. On retourne une réponse
LinkValue #TheGreatPlaceToGeek
Les différents tests
Rouge : Les tests unitaires
Orange : les tests d’intégrations
Vert : les tests fonctionnels
LinkValue #TheGreatPlaceToGeek
Ecrire un Test unitaire● Déclarez les mocks
des dépendances de la classe testée en attribut de la classe de test.
● Idem pour la config
LinkValue #TheGreatPlaceToGeek
Ecrire un Test unitaire● Dans l’exercise,
définissez le comportement de votre test
● Dans le verify assurez vous de la réponse attendue. Un test doit contenir au moins une assertion
LinkValue #TheGreatPlaceToGeek
Ecrire un Test unitaire● Testez les appels des
méthodes de vos mocks ainsi que le nombre d’appels
● Testez également les paramètres passés en argument
● Surveillez toutes les étapes d’avancement de votre code
LinkValue #TheGreatPlaceToGeek
Ecrire un Test unitaire● Ne tester que des comportements attendus: inutile de s’assurer qu’une
méthode non utilisée n’est pas appelée
● N’utilisez pas les dataProviders pour tester plusieurs fois le même cas de figure.
● Faites toujours attention de tester le comportement attendu de votre code et non le code écrit
LinkValue #TheGreatPlaceToGeek
Ecrire un Test d’intégration● On ne teste pas le bon
fonctionnement des différentes couches, on teste leurs intéractions
● On mock les dépendances externes (webservice, BDD …) qui pourrait faire échouer les tests alors que le code est bon
● On ne vérifie pas le résultat des dépendances, on vérifie la réponse de la méthode testée
LinkValue #TheGreatPlaceToGeek
Ecrire un Test d’intégration
● Utilisez intelligemment les mocks, mais pas trop
● Dans cet exemple l’objet User ne devrait pas être mocké
● Ne mockez que les classes qui comportent des dépendances externes
LinkValue #TheGreatPlaceToGeek
Ecrire un Test d’intégration
● Un test d’intégration intervient dès lors qu’on teste plusieurs classes
● Il ne remplace pas un test unitaire, il le complète
● Les tests d’intégrations sont souvent plus lents et plus fragiles que les tests unitaires
LinkValue #TheGreatPlaceToGeek
Ecrire un test fonctionnel● Ne vous appuyez pas sur les
données de fixtures
● Utilisez des transactions pour vos appels en bdd
● Configurer le lancement de la transaction dans le setUp et son rollback dans le tearDown
LinkValue #TheGreatPlaceToGeek
Ecrire un test fonctionnel● Ne vous occupez pas du code
● Testez uniquement le résultat
● Testez une valeur fixe seulement si elle est unique
● Ne testez qu’un seul comportement par test
LinkValue #TheGreatPlaceToGeek
Ecrire un test fonctionnelLes tests fonctionnels doivent être lancés sur un serveur applicatif dédié et iso prod.
Pour les dépendances externes (API) : ● Si une version de test existe, configurez et appelez l’api de test● Si vous appelez une api de prod, connaissez les données retournées
Pour la base de données: ● Appelez une base de données de test● Utilisez des fixtures pour remplir la base de donnée
Test Driven Developement
LinkValue #TheGreatPlaceToGeek
Késako ?
● TDD : Acronyme de Test Driven Development
● Développement piloté par les tests
● Ecrire le test avant le code
LinkValue #TheGreatPlaceToGeek
Process TDD1. On écrit le test
2. On vérifie que le test échoue
3. On écrit le code le plus vite possible
4. On vérifie que tous les tests soient verts
5. On refactorise le code proprement
LinkValue #TheGreatPlaceToGeek
Pourquoi travailler en TDD
● Structure le code avant écriture
● Participe intégralement au process de développement
● Evite l’écriture de tests qui valident le code existant
LinkValue #TheGreatPlaceToGeek
Difficultés● Simple à comprendre, moins à utiliser
● Nécessite de la pratique
● Force à réapprendre une logique de développement
● Chercher le rouge, ne jamais le commiter
La Team DD
LinkValue #TheGreatPlaceToGeek
Problèmatique TDD
● Ca sert à quoi d’écrire les tests en premiers ?
● Je dois tout tester ou seulement certaines choses ?
● Que dois-je tester en premier ?
LinkValue #TheGreatPlaceToGeek
BDD à la rescousse
● TDD : Incite le développeur à se poser les bonnes questions
● BDD : Behaviour Driven Development.Aide les différents corps de métiers à se poser les bonnes questions ensemble
LinkValue #TheGreatPlaceToGeek
Scénariser les tests● Les tests ne sont plus écrits par les développeurs à partir du cahier
des charges
● Client et développeurs décident ensemble des tests à écrire
● Ecriture de scénario décrivant le comportement de l’application et donc le comportement à tester
● Utilisation d’un langage commun entre le client et le développeur : le gherkin
LinkValue #TheGreatPlaceToGeek
Comment tu me causes ?
● Utilisation d’un “ubiquitous language” gherkin
● Compréhensible par l’ensemble des métiers
● Utilise la matrice Given/When/Then pour écriture de scénario
LinkValue #TheGreatPlaceToGeek
Ecrire un scénario● Votre scénario décrit le
comportement attendu
● Given pose le contexte
● When indique le déroulement de l’action
● Then le résultat attendu
LinkValue #TheGreatPlaceToGeek
Coder un scénario● Le code reprend les étapes
setUp / exercise / Verify
● BDD permet de coder des tests fonctionnels
● Ces tests fonctionnels serviront alors de scénario pour les tests unitaires
LinkValue #TheGreatPlaceToGeek
BDD + TDD1. (story) Pour chaque scénario décrivant la fonctionnalité
2. (RED) Lancer le scénario qui va échouer
3. (RED) Définir la première étape
4. (GREEN) Ecrire le code de l’étape pour la faire passer
5. (REFACTOR) Refactorer le code et répéter les étapes 4&5 pour chaque étape jusqu’à ...
6. (GREEN) Le scénario passe
7. (REFACTOR) Refactorer le code de l’application
LinkValue #TheGreatPlaceToGeek
BDD + TDD
● L’écriture des tests est dirigée par les scénarios
● BDD n’est pas un remplacant de TDD
● Concept de développement Agile
LinkValue #TheGreatPlaceToGeek
BDD + TDD + DDD
LinkValue #TheGreatPlaceToGeek
Pour Conclure● Tester c’est inutile : Seuls les mauvais développeurs ne doutent pas
de leur code
● C’est trop difficile : Non, mais cela demande de l’investissement. Les bonnes pratiques et les patterns de tests aident pour démarrer
● C’est irréaliste : Regardez autour de vous ! Sur github tout type de projet et de toute taille les utilisent et fonctionnent. C’est plus régulier de trouver un projet couvert par les tests
● C’est pas mon job : As tu déjà réfléchis à une reconversion ? Les tests c’est du code
LinkValue #TheGreatPlaceToGeek
Questions ?
LinkValue #TheGreatPlaceToGeek
Sources:
● http://www.thedarksideofthewebblog.com/les-mocks-sont-ils-nos-amis/
● http://blog.viseo-bt.com/tests-unitaires-dintegration-fonctionnel-metier-comment-les-definir/
● http://blog.xebia.fr/2008/04/11/les-10-commandements-des-tests-unitaires/
● http://blog.soat.fr/2013/09/10-trucs-infaillibles-pour-rater-ses-tests-unitaires-en-toutes-circonstances-12/
● http://agilitateur.azeau.com/post/2010/09/05/Stub-et-Mock-montent-sur-sc%C3%A8ne
● http://agilitateur.azeau.com/post/2011/04/12/Pour-en-finir-avec-les-Stubs-et-les-Mocks
● http://xunitpatterns.com/
● http://xunitpatterns.com/Test%20Stub.html
● http://fr.slideshare.net/ohoareau/intro-sur-les-tests-unitaires